繁体   English   中英

如何在scala中返回一个函数

[英]How to return a function in scala

如何在Scala中返回一个 函数 副作用词法闭包 1

例如,我在Go中查看此代码示例

...    
// fib returns a function that returns
// successive Fibonacci numbers.
func fib() func() int {
    a, b := 0, 1
    return func() int {
        a, b = b, a+b
        return b
    }
}
...
println(f(), f(), f(), f(), f())

打印1 2 3 5 8

我无法弄清楚如何在Scala中编写相同的内容。

1.在Apocalisp评论后更正

稍微短一点,你不需要退货。

def fib() = {
    var a = 0
    var b = 1
    () => { 
        val t = a;
        a = b
        b = t + b
        b
    }
}

尔加! 可变变量?!

val fib: Stream[Int] =
  1 #:: 1 #:: (fib zip fib.tail map Function.tupled(_+_))

您可以返回获取第n个fib的文字函数,例如:

val fibAt: Int => Int = fib drop _ head

编辑:既然你要求“每次调用f时获得不同的值”的功能方式,这就是你如何做到这一点。 这使用Scalaz的State monad:

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的次数。 但这完全是功能性的,因此模块化和可组合。 例如,我们可以传递任何非空的Stream,而不仅仅是fib

所以你看,你可以有没有副作用的效果。

虽然我们正在分享与该问题仅相关的斐波那契函数的酷实现,但这里是一个memoized版本:

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)
}

它使用memoizing定点组合器作为这个问题的答案: 在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
}

得到它了!! 经过一些试验和错误后:

def fib() : () => Int = {
    var a = 0
    var b = 1
    return (()=>{ 
        val t = a;
        a = b
        b = t + b
        b
    })
}

测试:

val f = fib()
println(f(),f(),f(),f())

1 2 3 5 8

使用元组时不需要temp var:

def fib() = {
  var t = (1,-1)
  () => { 
    t = (t._1 + t._2, t._1)
    t._1
  }
}

但在现实生活中你应该使用Apocalisp的解决方案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM