代码之家  ›  专栏  ›  技术社区  ›  OscarRyz

如何在scala中返回函数

  •  17
  • OscarRyz  · 技术社区  · 15 年前

    我怎么能还 功能 side-effecting lexical closure 在斯卡拉?

    例如,我在看 this code sample in 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来写。

    一。修正后 Apocalisp 评论

    5 回复  |  直到 9 年前
        1
  •  21
  •   fedesilva    15 年前

    稍微短一点,你不需要回报。

    def fib() = {
        var a = 0
        var b = 1
        () => { 
            val t = a;
            a = b
            b = t + b
            b
        }
    }
    
        2
  •  20
  •   Apocalisp    9 年前

    啊!可变变量?!

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

    可以返回得到第n个fib的文本函数,例如:

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

    编辑:既然你要求“每次调用f时获取不同的值”的功能方法,下面是你的方法。这用的是斯卡拉 State 蒙纳德:

    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型 . 但这都是纯功能的,因此是模块化的,可组合的。例如,我们可以传递任何非空流,而不仅仅是 小谎 .

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

        3
  •  8
  •   Community Mohan Dere    9 年前

    虽然我们分享了斐波纳契函数的一些很酷的实现,这些实现只与问题相关,但这里有一个记忆版本:

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

    它使用记忆定点组合器来回答这个问题: In Scala 2.8, what type to use to store an in-memory mutable data table?

    顺便说一句,combinator的实现为实现 功能 影响词汇闭合的因素:

    def fib(): () => Int = {
       var a = 0
       var b = 1
       def f(): Int = {
          val t = a;
          a = b
          b = t + b
          b
      }
      f
    }
    
        4
  •  3
  •   OscarRyz    15 年前

    知道了!!经过反复试验:

    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
    
        5
  •  1
  •   Landei    15 年前

    使用元组时不需要临时变量:

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

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

    推荐文章