scala 如何在scala中返回一个函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4262241/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 02:35:40  来源:igfitidea点击:

How to return a function in scala

functionscalareturn-valuego

提问by OscarRyz

How can I return a functionside-effecting lexical closure1in Scala?

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

For instance, I was looking at this code sample in Go:

例如,我在 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())

prints 1 2 3 5 8

打印 1 2 3 5 8

And I can't figure out how to write the same in Scala.

而且我不知道如何在 Scala 中编写相同的内容。

1. Corrected after Apocalispcomment

1.在Apocalisp评论后更正

回答by fedesilva

Slightly shorter, you don't need the return.

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

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

回答by Apocalisp

Gah! Mutable variables?!

嘎!可变变量?!

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

You can return a literal function that gets the nth fib, for example:

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

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

EDIT: Since you asked for the functional way of "getting a different value each time you call f", here's how you would do that. This uses Scalaz's Statemonad:

编辑:由于您要求“每次调用 f 时都获得不同的值”的功能方式,因此您将如何做到这一点。这使用了 Scalaz 的Statemonad:

import scalaz._
import Scalaz._

def uncons[A](s: Stream[A]) = (s.tail, s.head)
val f = state(uncons[Int])

The value fis a state transition function. Given a stream, it will return its head, and "mutate" the stream on the side by taking its tail. Note that fis totally oblivious to fib. Here's a REPL session illustrating how this works:

该值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@d53513

scala> (for { _ <- f; _ <- f; _ <- f; x <- f } yield x)
res30: scalaz.State[scala.collection.immutable.Stream[Int],Int]  = scalaz.States$$anon@1ad0ff8

scala> res29 ! fib
res31: Int = 5

scala> res30 ! fib
res32: Int = 3

Clearly, the value you get out depends on the number of times you call f. But this is all purely functional and therefore modular and composable. For example, we can pass any nonempty Stream, not just fib.

显然,您得到的值取决于您调用 的次数f。但这都是纯粹的功能性,因此是模块化和可组合的。例如,我们可以传递任何非空 Stream,而不仅仅是fib.

So you see, you can have effects without side-effects.

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

回答by Aaron Novstrup

While we're sharing cool implementations of the fibonacci function that are only tangentially related to the question, here's a memoized version:

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

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

It uses the memoizing fixed-point combinator implemented as an answer to this question: In Scala 2.8, what type to use to store an in-memory mutable data table?

它使用 memoizing 定点组合器作为这个问题的答案:在 Scala 2.8 中,使用什么类型来存储内存中的可变数据表?

Incidentally, the implementation of the combinator suggests a slightly more explicit technique for implementing your functionside-effecting lexical closure:

顺便说一下,组合子的实现提出了一种稍微更明确的技术来实现你的函数副作用词法闭包:

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

回答by OscarRyz

Got it!! after some trial and error:

知道了!!经过一些试验和错误:

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

Testing:

测试:

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

1 2 3 5 8

回答by Landei

You don't need a temp var when using a tuple:

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

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

But in real life you should use Apocalisp's solution.

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