scala:功能和功能之间的区别_

时间:2018-01-05 18:40:08

标签: scala

在Scala中使用名称函数调用时,我遇到了一些意外行为。谁能解释一下这里的区别呢?

class Button( act: => Unit) {def fire = act}
def foo() {println("foo got called")}
val x= new Button(foo)
x.fire
val y= new Button(foo _)
y.fire

x.fire导致调用foo。 y.fire没有。 为什么? 传递给y的功能是什么? 谢谢!

3 个答案:

答案 0 :(得分:4)

你应该对你的课程定义不同。

class Button( act: () => Unit) {def fire = act()}

请注意,您现在正在使用Function0[Unit]而不是按名称Unit取值。这个新定义有更好的类型,因为它需要一个函数,而你的接受任何值,除非有评估传入的值所需的副作用,否则什么也不做。我们现在也调用传入的函数来代替它的副作用回来吧。

Unit的问题在于,当需要一个单位时,可以提供任何值,该值将自动为Unit丢弃。例如,代码new Button(5)有效,代码为val x: Unit = 5

第一个代码class Button( act: => Unit) {def fire = act}“工作”的原因是,您调用方法foo,并将结果传递给Button构造函数。因为它是一个名字参数foo在它被使用之前实际上不会运行。然后,当您使用传递给类的Unit值时,需要对表达式求值,因此foo很有趣。

您的第二个示例是不同的,但是添加下划线(foo _)现在意味着您将方法本身作为函数传递,而不是像第一个示例中那样调用方法并传入结果。将函数传递给构造函数是完全正常的,即使现在的类型不是Unit,因为如前所述,任何值都可以被丢弃并替换为Unit。当你评估Unit值时,这次没有副作用,因为你没有运行方法来获取单位,只需创建一个在不运行的情况下被丢弃的函数。 def fire = act

将类型更改为函数时。

class Button( act: () => Unit) {def fire = act()}

现在只有() => Unit是一个有效的参数而不是任何东西,而fire方法运行该函数。

答案 1 :(得分:3)

这是一个可能的解释!

scala> foo _
res14: () => Unit = <function0>

scala> foo
foo got called

scala>

你能明白为什么吗?

答案 2 :(得分:2)

由于Button将(延迟的)Unit作为构造函数参数,因此您认为不允许调用new Button(foo _),因为() => Unit不是与=>Unit相同。但事实证明,=> Unit基本上是普遍接受者。

new Button()
new Button(99)
new Button("str")

你会得到警告,但这些都是编译和运行的,你可以在它们上调用fire方法(但它不会做任何事情)。