Одним из важных свойств чисто функциональной программы, в которой отсутствуют изменяемые переменные и другие побочные эффекты, является то, что значение, которое оценивается выражением, зависит только от самого выражения. Это не зависит от того, в каком порядке оцениваются вещи (слева направо, справа налево, строго, лениво), от состояния операционной системы, времени суток и т. д.
В частности, это означает, что в чисто функциональной настройке каждый вызов new C
будет возвращать полностью идентичный объект-счетчик. Обычно это хорошо, потому что так легче рассуждать о вашей программе, но это как бы мешает тому, что вы пытаетесь там сделать. Чтобы сделать объекты C разными, вам нужно явно передать значения их счетчиков, что, честно говоря, просто заметает проблему под ковер.
val c1 = new C(0)
val c2 = new C(1)
Если вы хотите иметь глобальную переменную «счетчик», такую как переменная внутреннего класса, которую вы использовали, один из возможных способов реализовать ее в чисто функциональной настройке - передать значение счетчика каждой функции, которой нужен счетчик, и чтобы эти функции также возвращали обновленная версия счетчика. Для краткого примера:
def increment_counter(n: Int): Int = { n + 1)
def create_c(n: Int): (C, Int) = {
val c = new C(n)
val n' = increment_counter n
(c, n')
}
val n = 0
val (c1, n') = create_c(n)
val (c2, n'') = create_c(n')
val n' = increment_counter(n)
Вы можете структурировать это немного лучше с помощью шаблона State Monad (в большинстве случаев знакомства с монадами он будет, вероятно, использоваться в качестве примера).
Однако вполне возможно, что это окажется более сложным, чем просто использование изменяемой переменной для счетчика. Фактически, я обычно использую изменяемые переменные для этих "глобально увеличивающихся счетчиков" в функциональных языках, которые позволяют мне это делать.
person
hugomg
schedule
30.11.2016