具体而言,遵循两个定义有何不同之处:
def func(f: () => String) = f()
def func1(s: String) = s
我写了一些代码来测试它们,似乎它们产生了相同的结果;在这种情况下,这两个定义是否相同;或者他们确实有一些区别?
var x = 1
def f() = {
x = x + 1
s"$x"
}
println(func1(f))
println(func1(f))
println(func1(f))
println(func(f))
println(func(f))
println(func(f))
答案 0 :(得分:2)
在这种情况下它们可能是相同的,但是当() => A
和A
有很大不同时,还有很多其他情况。 () => A
被称为thunk,用于将一段延迟计算传递给函数。在被调用的函数决定对其进行评估之前,“thunk”的主体不会被评估。 Otherwitse,传入的参数的值由调用者计算。
考虑这个例子,其中采用thunk的版本与仅采用值的版本之间存在差异:
object Thunk {
def withThunk(f: () ⇒ String): Unit = {
println("withThunk before")
println("the thunk's value is: " + f())
println("now the thunk's value is: " + f())
}
def withoutThunk(f: String): Unit = {
println("withoutThunk before")
println("now the value's value is: " + f)
}
def main(argv: Array[String]): Unit = {
withThunk { () ⇒ println("i'm inside a thunk"); "thunk value" }
println("------------")
withoutThunk { println("i'm not inside a thunk"); "just a value" }
}
}
该计划将展示一些差异。在thunk版本中,你看到“withThunk before”在第一次“我在一个thunk里面”被打印之前被打印出来,打印两次,因为f()被评估两次。在非thunk版本中,“我不在thunk里面”在“之前的onThunk”之前被打印,因为这是在作为参数发送给函数之前被评估的。
答案 1 :(得分:1)
def func(f: () => String) = f()
这个接受一个返回字符串的函数作为参数。
def func1(s: String) = s
虽然这个简单需要String作为参数
除了上面的小技术差异之外,在这种情况下,它们似乎功能相同。但是,函数参数可能更强大,因为它是一个可以从其他几个操作派生返回值的函数。但是,我认为,函数参数允许您决定何时导出值的主要区别。
答案 2 :(得分:1)
我想添加一个使用() => String
的示例。
def printFuncResult(f: () => String) = println(f() + " " + f())
def ran = () => Math.random.toString
printFuncResult(ran)
printFuncResult(Math.random.toString)
当您传递像ran
这样的函数时,您很可能会打印两个不同的值(此处涉及随机性)。当您传递固定的随机数时,它将被打印两次。
正如您所看到的:当您将函数作为参数时,每次在printFuncResult
中使用它时,它可能会产生不同的值。只需输入String
参数即可实现此目的。
答案 3 :(得分:1)
def func(f: () => String) = f()
def func1(s: String) = s
println(func1(f)) // in this case f is evaluated first, its value is used in func1.
println(func(f)) // in this case f is NOT evaluated, but passed as it is to func.
// It is upto func to call f whenever needed, or even not call it.
这是f的“懒惰”评估,它使func更有用,例如f可以传递给其他一些更高阶的函数,或者它可以异步调用。