Scala中的名称参数

时间:2018-04-07 12:46:29

标签: scala pass-by-name

从“Scala编程”一书中可以看出:

var assertionsEnabled = true
def myAssert(predicate: () => Boolean) =
if (assertionsEnabled && !predicate())
throw new AssertionError

myAssert(() => 5 > 3)

使用空参数列表很尴尬。 Scala提供了by-name参数来解决这个问题。

def byNameAssert(predicate: => Boolean) =
if (assertionsEnabled && !predicate)
throw new AssertionError

byNameAssert(5 > 3)

我在讨论中有一个混乱.myAssert接受一个函数参数,该参数不带参数并返回一个布尔值。

byNameAssert的输入类型是什么?与myAssert相同吗?对我来说,似乎是一个表达式,它计算为一个布尔值,并且以名字形式表示它表示只要调用表达式就会计算,而不是被传递给byAssert.But然后它与myAssert的输入类型不同。如果是这种情况,那么byAsAssert和myAssert是完全不同的。

2 个答案:

答案 0 :(得分:0)

  

对我来说,它似乎是一个表达式,它计算为一个布尔值,并且以名字形式表示它意味着只要调用它就会计算表达式,而不是在传递给byAsAssert时计算它。

是。但它实现的方式是Scala将byNameAssertmyAssert编译为完全相同的代码(不同的@ScalaSignature注释除外)以及每当它看到{{1}之类的调用时它们被重写,因此下一个编译器阶段将参数视为byNameAssert(5 > 3)

答案 1 :(得分:0)

  

byNameAssert的输入类型是什么?

=> Boolean

  

与myAssert相同吗?

不,myAssert期望() => Boolean作为参数。虽然"道德相同",但它被编译器视为一个单独的类型。

=> Boolean - 事物既不是() => Boolean,也不是Boolean。以下小例子应该进一步说明这一点。尝试将有条件的foo分配给() => BooleanBoolean类型的变量失败:

scala> def foo(b: => Boolean): Unit = {}
foo: (b: => Boolean)Unit

scala> val f: Boolean => Unit = foo _
<console>:12: error: type mismatch;
 found   : (=> Boolean) => Unit
 required: Boolean => Unit
       val f: Boolean => Unit = foo _
                                ^

scala> val f: (() => Boolean) => Unit = foo _
<console>:12: error: type mismatch;
 found   : (=> Boolean) => Unit
 required: (() => Boolean) => Unit
       val f: (() => Boolean) => Unit = foo _
                                        ^

但这有效:

scala> val f: (=> Boolean) => Unit = foo _
f: (=> Boolean) => Unit = $$Lambda$1090/668948486@69bc9584

因此,虽然从实现的角度来看,=> Boolean() => Boolean基本相同,但它被分别视为一种不同的类型,并且当涉及到语法脱离时它的行为完全不同表达式和代码块作为参数传递给函数。