0

I'm learning Scala and confused about the try-catch-finally syntax.

In Scala Syntax Specification, it says:

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

Can I write expression without { } blocks like this:

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

Or the expression must be a block expression ?

linrongbin
  • 2,967
  • 6
  • 31
  • 59
  • 6
    This has nothing to do with Java. Why don't you just try it and see? – Michael Aug 24 '20 at 09:32
  • 6
    I wonder what's the motivation behind the questions, where it takes more time to ask them than just run in the console... – Andronicus Aug 24 '20 at 09:34
  • 1
    First-person experimentation is the best way to learn, but I assume the OP is a bit confused by Scala's syntax (which is why the `catch` expression is not valid in the post) and couldn't understand the compiler error enough to make sense of it. – stefanobaghino Aug 24 '20 at 10:05
  • Downvoting because this can be trivially tried out – Matthias Berndt Aug 24 '20 at 17:31

2 Answers2

5

Scala 3 (Dotty) is experimenting with optional braces (significant indentation) so the following works

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 = ()

where we note the handler

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

did not need braces as in Scala 2. In fact due to special treatment of case clauses after catch keyword the following would also work

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 = ()

where we note the handler did not have to be indented after catch

catch
case e => println(s"good catch $e")
Mario Galic
  • 47,285
  • 6
  • 56
  • 98
4

Sure.

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")))

This compiles and runs as expected, although I had to define the catch expression separately (as it requires braces).

You can play around with this code here on Scastie.

A few of notes:

  • try/catch/finally is an expression that returns a value (this could be a bit unfamiliar if you're coming from Java) -- you can read more about it here on the docs
  • catch always takes a PartialFunction from a Throwable to some type, with the overall return type of the try/catch to be the closest common superclass of the two (e.g. say you have class Animal; class Dog extends Animal; class Cat extends Animal, if the try returns a Dog and the catch returns a Cat the overall expression will return an Animal)
  • I used the NonFatal extractor in the catch partial function, you can read more about it in this answer, while extractor objects in general are described here in the official docs
stefanobaghino
  • 11,253
  • 4
  • 35
  • 63