我不知道如何表达我的问题,除了提供一个我想做的事情的例子,并解释为什么它不起作用。
我想做以下事情:
def yes() { println("yes") }
def no() { println("no") }
def blank() {}
var handler: Option[() => Unit] = Some(blank)
...
handler = Some(yes)
...
handler.foreach(f => f())
这不起作用,因为定义的函数是Unit类型,而不是()=>单元。所以有些(空白)不能被指定为类型选项[()=>单位]。
接下来我尝试了:
var handler: Option[Unit] = Some(blank)
...
handler = Some(yes)
...
handler.foreach(f => f())
这允许我将函数分配给处理程序,但是我无法在Option的foreach函数中调用该函数。
如何实现这一目标?
答案 0 :(得分:5)
这不起作用,因为定义的函数是Unit类型,而不是 ()=>单元。所以有些(空白)不能被指定为类型 选项[()=>单位]
。
实际上它按预期工作。
表达式yes()
的类型为Unit
,但表达式yes
的类型取决于上下文。
在() => Unit
编译器的上下文中,可以将yes
转换为类似() => yes()
的内容。
您可以手动创建方法() => Unit
中的函数yes
,如下所示:
val functionYes = yes _
handler = Some(functionYes)
但编译器足够智能,可以在需要函数的上下文中将方法转换为函数,如Some(yes)
。
看一下这个例子:
1 to 10 foreach println
println
这里是方法Predef.println
,因此编译器必须将其转换为函数。
答案 1 :(得分:2)
这里值得提供一些词汇。
方法的类型
def foo(): Unit = ???
是()Unit
(规范中的3.3.1方法类型)。
如果你放弃了parens,
def foo: Unit = ???
然后类型为=> Unit
。
规范的那一部分称它们为“非值类型”,因为你不能将它们用作值。
如果您想要类型为() => Unit
的值,则会应用转化。见规范的6.26.5,称为“eta扩展”。
我打赌你在某个时候离开了parens看到了失败:
scala> def foo: Unit = ???
foo: Unit
scala> var handler: Option[() => Unit] = Some(foo)
<console>:8: error: type mismatch;
found : Unit
required: () => Unit
var handler: Option[() => Unit] = Some(foo)
^
在这种情况下,您获得的转换是“评估”(6.26.2)。
如果您在方法定义中提供了parens,那么这很重要。
由于不推荐使用“过程语法”,因此练习不使用它可能很有用。