3 回答
TA贡献1864条经验 获得超6个赞
稍短一些,您不需要退货。
def fib() = {
var a = 0
var b = 1
() => {
val t = a;
a = b
b = t + b
b
}
}
TA贡献1993条经验 获得超5个赞
加!可变变量?!
val fib: Stream[Int] =
1 #:: 1 #:: (fib zip fib.tail map Function.tupled(_+_))
您可以返回获取第n个fib的文字函数,例如:
val fibAt: Int => Int = fib drop _ head
编辑:由于您要求“每次调用f都会获得不同的值”的功能性方法,因此,您将按照以下方法进行操作。这使用了Scalaz的Statemonad:
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。
因此,您可以看到没有副作用的效果。
TA贡献1785条经验 获得超4个赞
尽管我们共享的斐波那契函数很酷的实现仅与问题有切线关系,但这里是一个简要记录的版本:
val fib: Int => BigInt = {
def fibRec(f: Int => BigInt)(n: Int): BigInt = {
if (n == 0) 1
else if (n == 1) 1
else (f(n-1) + f(n-2))
}
Memoize.Y(fibRec)
}
它使用实现该问题的答案的记忆定点组合器:在Scala 2.8中,用于存储内存可变数据表的类型是什么?
顺便说一下,组合器的实现提出了一种稍微更明确的技术,用于实现函数副作用词法闭包:
def fib(): () => Int = {
var a = 0
var b = 1
def f(): Int = {
val t = a;
a = b
b = t + b
b
}
f
}
- 3 回答
- 0 关注
- 225 浏览
添加回答
举报