创建一个类型函数的选项,以便稍后执行该函数?

时间:2014-01-06 20:38:48

标签: scala

我不知道如何表达我的问题,除了提供一个我想做的事情的例子,并解释为什么它不起作用。

我想做以下事情:

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函数中调用该函数。

如何实现这一目标?

2 个答案:

答案 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,那么这很重要。

由于不推荐使用“过程语法”,因此练习不使用它可能很有用。