2017-02-19 3 views
0

Scala newbie пытается реализовать метод с именем «counter», подпись метода которого ниже.Scala: отдельные состояния переменной count внутри возвращаемого метода

Метод должен быть функцией без состояния, так что, когда он вызывается с целым числом n, он возвращает функцию состояния. Эта функция состояния должна возвращать n при ее первом вызове, затем n + 1, затем n + 2 и т. Д.

Счетчики должны быть независимыми, чтобы сработавший счетчик (1) дважды выполнял две функции, которые не мешают каждому чужого государства.

Ниже то, что я до сих пор:

val counter : Int =>() => Int = { 
    // Complete definition below. 
    var count = 0 

    n: Int =>() => { 
     var returnVal = n + count 
     count = count + 1 
     returnVal 
    } 
} 

пример того, как называется счетчик:

assert ({ 
    val k1 :() => Int = counter (1) 
    val k2 :() => Int = counter (2) 
    val r1 : Int = k1() 
    val r2 : Int = k1() 
    val r3 : Int = k2() 
    val r4 : Int = k2() 
    val r5 : Int = k2() 
    val r6 : Int = k1() 
    (r1, r2, r3, r4, r5, r6) 
    } === (1, 2, 2, 3, 4, 3) 
) 

При запуске утверждают, моя реализация встречных деклараций (1, 2, 4 , 5, 6, 6).

Я считаю, что это связано с k1 и k2, указывающими на одну и ту же переменную счета. Однако я не могу понять, как бы я предоставил k1 и k2 свою собственную отдельную переменную счетчика, чтобы они «не мешали друг другу», согласно требованиям.

Есть ли я на правильном пути? Любые рекомендации будут оценены наиболее высоко.

ответ

2

Во-первых, проверьте the difference between def and val. TL; DR - это то, что val будет оценивать только один раз, поэтому вы не можете действительно зависеть от переменной count-hold, если вы определяете ее в counter, прежде чем перейти к функции, которую хотите вернуть.

Чтобы сделать его более ясным, я добавил круглые скобки, чтобы сделать совпадение шаблонов более очевидным и разломало эту строку, потому что нам нужно было захватить параметр, который был передан в counter, и сохранить его в закрытии для анонимной функции, возвращение.

val counter : Int =>() => Int = { 
    (n: Int) => { 
    var count = n 

    () => { 
     val returnVal = count 
     count = count + 1 
     returnVal 
    } 
    } 
} 
+0

Это сработало отлично. Спасибо! – shoogazer

+3

Не то, чтобы это было важно здесь, но я бы сделал 'returnVal'' val'. –

+0

Хороший звонок @ Джаспер-М. – bergren2

1

Вы должны изменить ключевое слово из val в def для метода счетчик вы определяете:

def counter : Int =>() => Int = { 
    // Complete definition below. 
    var count = 0 

    n: Int =>() => { 
     var returnVal = n + count 
     count = count + 1 
     returnVal 
    } 
} 

Потому что с val, то граф переменная определена только один раз, который происходит, когда вы определите счетчик метод, поэтому позже все блокировки будут разделять эту переменную; с методом def, счет переменная будет переопределяться каждый раз, когда вы звоните счетчик (n).


Это легче увидеть, если добавить Println после var count = 0 линии:

scala> val counter : Int =>() => Int = { 
      // Complete definition below. 
      var count = 0 
      println(count) 

      n: Int =>() => { 
       var returnVal = n + count 
       count = count + 1 
       returnVal 
      } 
     } 

0           // 0 is printed here 
counter: Int => (() => Int) = <function1> 

scala> val k1 = counter(1)     // nothing prints here 
k1:() => Int = <function0> 

scala> val k2 = counter(2)     // nothing prints here 
k2:() => Int = <function0> 
+0

Спасибо, это имеет смысл. К сожалению, я должен сохранить ключевое слово val в соответствии с рекомендациями задания. – shoogazer

Смежные вопросы