0

从“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 相同吗?对我来说,它似乎是一个计算结果为布尔值的表达式,并且以名称形式表示意味着表达式在被调用时被计算,而不是在被传递给时被计算byNameAssert。但是它与 myAssert 的输入类型不同。如果是这样的话,那么 byNameAssert 和 myAssert 就完全不同了。

4

2 回答 2

0

对我来说,它似乎是一个计算为布尔值的表达式,并且以名称形式表示它意味着每当调用它而不是传递给 byNameAssert 时都会计算表达式。

是的。但它的实现方式是 Scala 编译byNameAssertmyAssert生成完全相同的代码(除了不同的@ScalaSignature注释),并且每当它看到调用时就像byNameAssert(5 > 3)它们被重写一样,所以下一个编译器阶段会看到参数() => 5 > 3

于 2018-04-07T13:06:17.150 回答
0

byNameAssert 的输入类型是什么?

=> Boolean

和 myAssert 一样吗?

不,myAssert期望() => Boolean作为论点。虽然“道德上相同”,但编译器将其视为单独的类型。

-=> Boolean事物既不是() => Boolean,也不是Boolean。下面的小例子应该进一步说明这一点。尝试将 curried 分配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,但它被单独视为不同的类型,并且在对作为参数传递给函数的表达式和代码块进行句法脱糖时,它的行为完全不同。

于 2018-04-07T13:18:42.017 回答