在ShadowofCatron's Scala教程3视频 2:40之后,有人指出, 雷鸣 的名字后面的括号是可选的。"Buh?“我的函数式编程大脑说,因为函数的值和它应用时的值是完全不同的。
所以我写了下面的文章来试试这个。评论中描述了我的思维过程。
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在来到这个站点询问这个问题之后,我偶然发现了这个答案,它告诉我如何修复上面的Scala程序:
val b = f _ // Hey Scala, I mean f, not f()但是下划线‘提示’只是偶尔需要的。当我调用runThunk(f)时,不需要提示。但是当我用一个val别名f到b然后应用它时,它就不起作用了:应用程序发生在val中;甚至lazy val也是这样工作的,所以它不是导致这种行为的评估点。
所有这些都留给我一个问题:
为什么Scala 有时在计算它们时会自动应用块?
正如我所怀疑的那样,这是类型推断吗?如果是这样的话,类型系统不应该被排除在语言的语义之外吗?
这是个好主意吗Scala程序员是否更经常地应用块而不是引用它们的值,从而使parens可选的总体效果更好?
用Scala2.8.0RC3,DrScheme 4.0.1在R5RS中编写的示例。
发布于 2010-06-13 01:45:21
问题在于:
Buh?“我的函数式编程大脑说,因为一个函数的值和它应用时的值是完全不同的。
是的,但你没有声明任何函数。
def f(): Int = { counter = counter + 1; counter }您声明了一个名为f的方法,该方法有一个空参数列表,并返回Int。方法不是函数--它没有值。永远不要。您能做的最好的就是通过反射获得一个Method实例,这完全不是一回事。
val b = f _ // Hey Scala, I mean f, not f()那么,f _是什么意思呢?如果f是一个函数,它就意味着函数本身,当然,但这里不是这样的。它真正的意思是:
val b = () => f()换句话说,f _是方法调用的闭包。闭包是通过函数实现的。
最后,为什么Scala中的空参数列表是可选的?因为虽然Scala允许像def f = 5这样的声明,但是Java不允许。Java中的所有方法至少需要一个空参数列表。在Scala风格中,有许多这样的方法不会有任何参数(例如,length和size)。因此,为了使代码在空参数列表方面看起来更加统一,Scala使它们成为可选的。
发布于 2010-05-29 10:35:23
默认的原因,当您编写:
val b = f是评估函数并将结果分配给b,正如您已经注意到的。可以使用_,也可以显式指定b的类型。
// These all have the same effect
val b = f _
val b: () => Int = f
val b: Function0[Int] = f发布于 2010-05-29 11:33:48
在你的例子中
def f(): Int = { counter = counter + 1; counter }是定义方法而不是函数。AFAIK方法在Scala中根据上下文自动提升为函数。要定义一个可以编写的函数
val f = () => { counter = counter + 1; counter }我想你会得到你想要的。
https://stackoverflow.com/questions/2934568
复制相似问题