2

Try/catches can be used like an expression, so:

 scala> try { 3 } catch {case _ => 0}
 res52: Int = 3

Also:

scala> try { 3 } catch {case _ => 0} finally try {println("side effect")} catch { case _ => println("catching side effect") } 
side effect
res50: Int = 3

so why not:

 scala> try { 3 } catch {case _ => 0} + 4
 <console>:1: error: ';' expected but identifier found.
   try { 3 } catch {case _ => 0} + 4

or why not:

scala> try { 3 } catch {case _ => 0} match {case 3 => "hi"}
<console>:1: error: ';' expected but 'match' found.
   try { 3 } catch {case _ => 0} match {case 3 => "hi"}

My goal is a function definition like this:

def transact[T](code : Unit => T):T = 
   try {startTransaction; Right(code)} 
     catch {case t:Throwable => Left(t)} 
   finally try {endTransaction} 
     catch { case e:... if ... => throw e}  
 match  {
   case Right(e) => e
   case Left....
 }

Of course I could just store the try/catch in a val and match the val:

 def transact[T](code : Unit => T):T = 
 {
   val transa = try {startTransaction; Right(code)} 
     catch {case t:Throwable => Left(t)} 
   finally try {endTransaction} 
     catch { case e:... if ... => throw e}  
transa match { 
 case ...
}
}

but then it no longer is a single expression, and I need to wrap in another {} which - please corect me if I'm wrong- means another layer of function object wrapping aka indirection, at a performance critical place.

So, is there a way to use try as a full expression and avoid this indirection?

thanks

ib84
  • 675
  • 5
  • 16
  • 3
    `{}` does not create a function; it's just for logical grouping. If it so happens that a function is needed, then `{}` can group that stuff which is the body of the function. So `val x = {{{{{{{"fish"}}}}}}}` has zero function wrappers, while `Option(-5.0) map math.abs` has one. – Rex Kerr Nov 11 '12 at 14:00
  • 1
    `try` blocks are expressions indeed, but not all expressions are equal. See the accepted answer to [this question](http://stackoverflow.com/questions/7529668/scala-can-you-use-foo-match-bar-in-an-expression-without-parentheses) for more. In short, things like `if`, `match` and `try` blocks must be wrapped in parentheses to be treated as "full blown" expressions. – Philippe Nov 11 '12 at 14:02

1 Answers1

7

It's a scala grammar issue -- just add parenthesis to turn the try/catch block into a SimpleExpr so you can continue operating on it:

scala> (try { 3 } catch {case _ => 0}) + 4
res1: Int = 7

scala> (try { 3 } catch {case _ => 0}) match {case 3 => "hi"}
res2: java.lang.String = hi

As usual, curly and round brackets are (mostly) interchangeable -- your target code will look nicer (imo) with curly brackets.

No idea about indirections -- you would need to look at the compiled bytecode for that -- but I doubt it will make a difference.

For a full explanation on the grammar issue (which is not exactly an operator precedence issue as I initially believed), see: https://stackoverflow.com/a/7530565/178551

Community
  • 1
  • 1
jsalvata
  • 2,155
  • 15
  • 32
  • thanks. could you explain what an operator priority issue is, and why it occurs here? – ib84 Nov 11 '12 at 17:23
  • 1
    Proper English would be "operator precedence" -- but that's not really the explanation. I'll edit now. – jsalvata Nov 11 '12 at 18:45