Г!Изменяемые переменные?!
val fib: Stream[Int] =
1 #:: 1 #:: (fib zip fib.tail map Function.tupled(_+_))
Вы можете вернуть литеральную функцию, которая получает n-ый фиб, например:
val fibAt: Int => Int = fib drop _ head
РЕДАКТИРОВАТЬ: Поскольку вы запросили функциональный способ "полученияразные значения каждый раз, когда вы звоните ", вот как вы это сделаете.При этом используется State
монада Scalaz:
import scalaz._
import Scalaz._
def uncons[A](s: Stream[A]) = (s.tail, s.head)
val f = state(uncons[Int])
Значение f
является функцией перехода состояния.Учитывая поток, он вернет свою голову и "изменит" поток на стороне, взяв его за хвост.Обратите внимание, что f
полностью игнорирует fib
.Вот сеанс REPL, иллюстрирующий, как это работает:
scala> (for { _ <- f; _ <- f; _ <- f; _ <- f; x <- f } yield x)
res29: scalaz.State[scala.collection.immutable.Stream[Int],Int] = scalaz.States$$anon$1@d53513
scala> (for { _ <- f; _ <- f; _ <- f; x <- f } yield x)
res30: scalaz.State[scala.collection.immutable.Stream[Int],Int] = scalaz.States$$anon$1@1ad0ff8
scala> res29 ! fib
res31: Int = 5
scala> res30 ! fib
res32: Int = 3
Очевидно, что значение, которое вы получаете, зависит от того, сколько раз вы звоните f
.Но это все чисто функционально и потому модульно и составно.Например, мы можем пропустить любой непустой поток, а не только fib
.
Итак, вы видите, что вы можете иметь эффекты без побочных эффектов.