Scala的try-catch finally表达式可以不带大括号吗



我在学习Scala,对try-catch-finally语法感到困惑。

在Scala语法规范中,它说:

Expr1             ::=  ‘try’ Expr [‘catch’ Expr] [‘finally’ Expr]
| ...

我可以在没有{}块的情况下写这样的表达式吗:

try
println("Hello")
catch
RuntimeException e => println("" + e)
finally
println("World")

或者表达式必须是块表达式?

Scala 3(Dotty(正在尝试使用可选的大括号(显著缩进(,因此以下方法适用于

scala> try
|   1 / 0
| catch
|   case e => println(s"good catch $e")
| finally
|   println("Celebration dance :)")
|
good catch java.lang.ArithmeticException: / by zero
Celebration dance :)
val res1: AnyVal = ()

我们注意到处理程序

case e => println(s"good catch $e")

不像Scala 2中那样需要大括号。事实上,由于catch关键字后的case子句的特殊处理,以下内容也适用于

scala> try
|   1 / 0
| catch
| case e => println(s"good catch $e")
| finally
|   println("Celebration dance :)")
|
good catch java.lang.ArithmeticException: / by zero
Celebration dance :)
val res2: AnyVal = ()

其中我们注意到处理程序不必在catch之后缩进

catch
case e => println(s"good catch $e")

当然。

import scala.util.control.NonFatal
def fourtyseven: PartialFunction[Throwable, Int] = {
case NonFatal(_) => 47
}
def attempt(n: => Int): Int =
try n catch fourtyseven finally println("done")
println(attempt(42))
println(attempt(sys.error("welp")))

尽管我必须单独定义catch表达式(因为它需要大括号(,但它可以按预期编译和运行。

你可以在Scastie上玩这个代码。

注意事项:

  • try/catch/finally是一个返回值的表达式(如果您来自Java,这可能有点不熟悉(--您可以在文档中阅读更多关于它的信息
  • catch总是从Throwable取一个PartialFunction到某个类型,try/catch的整体返回类型是两者中最接近的公共超类(例如,假设您有class Animal; class Dog extends Animal; class Cat extends Animal,如果try返回Dogcatch返回Cat,则整个表达式将返回Animal(
  • 我在catch部分函数中使用了NonFatal提取器,您可以在这个答案中阅读更多关于它的信息,而提取器对象通常在官方文档中进行了描述

最新更新