就在 2 点 40 分之后卡特隆之影 http://www.youtube.com/user/ShadowofCatron's Scala 教程 3 视频 http://www.youtube.com/watch?v=R3gh9jIIbME,指出了a 名称后面的括号thunk http://en.wikipedia.org/wiki/Thunk#Functional_programming are optional。 “嗯?”我的函数式编程大脑说,因为函数的值和它在应用时评估的值是完全不同的东西。
所以我写了以下内容来尝试一下。评论中描述了我的思考过程。
object Main {
var counter: Int = 10
def f(): Int = { counter = counter + 1; counter }
def runThunk(t: () => Int): Int = { t() }
def main(args: Array[String]): Unit = {
val a = f() // I expect this to mean "apply f to no args"
println(a) // and apparently it does
val b = f // I expect this to mean "the value f", a function value
println(b) // but it's the value it evaluates to when applied to no args
println(b) // and the application happens immediately, not in the call
runThunk(b) // This is an error: it's not println doing something funny
runThunk(f) // Not an error: seems to be val doing something funny
}
}
为了清楚地说明问题,这个Scheme 程序(以及随后的控制台转储)显示了我期望Scala 程序执行的操作。
(define counter (list 10))
(define f (lambda ()
(set-car! counter (+ (car counter) 1))
(car counter)))
(define runThunk (lambda (t) (t)))
(define main (lambda args
(let ((a (f))
(b f))
(display a) (newline)
(display b) (newline)
(display b) (newline)
(runThunk b)
(runThunk f))))
> (main)
11
#<procedure:f>
#<procedure:f>
13
来到这个网站询问这个问题后,我发现这个答案 https://stackoverflow.com/questions/1450456/get-function-value-of-a-instance-method-in-scala/1450486#1450486它告诉我如何修复上述 Scala 程序:
val b = f _ // Hey Scala, I mean f, not f()
但只需要下划线“提示”有时。当我打电话时runThunk(f)
,不需要任何提示。但是当我用 a 将 f '别名' 为 b 时val
然后应用它,它不起作用:应用程序发生在val
;乃至lazy val
以这种方式工作,所以这不是导致这种行为的评估点。
这一切都给我留下了一个问题:
为什么斯卡拉有时在评估它们时自动应用 thunk?
正如我怀疑的那样,它是类型推断吗?如果是这样,类型系统不应该脱离语言的语义吗?
这是一个好主意吗? Scala 程序员是否应用 thunk 而不是引用它们的值更频繁地使括号可选总体上更好?
在 R5RS 中使用 Scala 2.8.0RC3、DrScheme 4.0.1 编写的示例。