在Foreach/Map块中抛出异常

Nic*_*len 9 scala

我很好奇为什么在下面的foreach块中抛出异常.我希望没有值使它通过过滤器,因此foreach永远不会到达块.出现相同的行为map.

scala> (1 to 10) filter { _ > 12 } foreach { throw new Exception }
java.lang.Exception
  ... 33 elided
Run Code Online (Sandbox Code Playgroud)

我希望异常不被抛出,并且表现得更像下面println从未执行过的地方.

scala> (1 to 10) filter { _ > 12 } foreach { println _ }
Run Code Online (Sandbox Code Playgroud)

也许这与如何处理异常有关?为什么是这样?

Lee*_*Lee 7

{ throw new Exception }
Run Code Online (Sandbox Code Playgroud)

只是一个抛出异常的块 - 因此它有类型Nothing.由于Nothing是所有类型的子类型,因此它与块Function[Int, T]的参数兼容foreach.

如果事先创建函数,则可以更清楚地看到这一点:

//throws exception
val f: Function[Int, Unit] = { throw new Exception }
Run Code Online (Sandbox Code Playgroud)

如果要创建Function[Int, Nothing],则需要将参数添加到块中:

(1 to 10) filter { _ > 12 } foreach { _ => throw new Exception }
Run Code Online (Sandbox Code Playgroud)

  • 换句话说,表达式"throw new Exception"是函数foreach的by-value参数,因此在执行较大的表达式之前对其进行求值.`_ => throw new Exception`也会首先被计算,但它会求值为一个函数对象(当较大的表达式执行时,它永远不会被调用). (8认同)