4

Possible Duplicate:
“return” and “try-catch-finally” block evaluation in scala

There are two Scala functions:

a): def foo(): Int = try { 1 } finally { 2 }

b): def bar(): Int = try { return 1 } finally { return 2}

I cannot figure out why foo returns 1 but bar returns 2.

Community
  • 1
  • 1
卢声远 Shengyuan Lu
  • 31,208
  • 22
  • 85
  • 130

2 Answers2

11

This behavior is explained in "Programming in Scala" by M.Odersky, L. Spoon and B.Venners. I have the first edition and section 7.5 (pg. 128) says:

it’s worth noting that Scala’s behavior differs from Java only because Java’s try-finally does not result in a value. As in Java, if a finally clause includes an explicit return statement, or throws an exception, that return value or exception will “overrule” any previous one that originated in the try block or one of its catch clauses. For example, given:

def f(): Int = try { return 1 } finally { return 2 }

calling f() results in 2. By contrast, given:

def g(): Int = try { 1 } finally { 2 }

calling g() results in 1. Both of these functions exhibit behavior that could surprise most programmers, thus it's usually best to avoid returning values from finally clauses.


Scala standard library has scala.util.control.Exception API that provides small functional library for handling exceptions. See the examples in scaladoc

Alexander Azarov
  • 12,971
  • 2
  • 50
  • 54
  • 2
    I came here after reading that section of Odersky. Unfortunately this answer doesn't really explain the behavior. I don't see why the finally block (the last code executed in the function) doesn't provide the return value for `foo`. – melston Sep 29 '18 at 20:16
1

The return statement of the finally block of bar() exits the method bar(). Therefor the result of the try block is not returned.

This example shows a (roughly) equivalent version of your methods foo() and bar():

object Test extends App {

    def foo() = {
      val result = { 1 }
      { 2 }
      result
    }

    def bar(): Int = {
      val result = { 1 }
      { return 2 }
      result // this line is not processed
    }

    println("foo = " + foo()) // foo = 1

    println("bar = " + bar()) // bar = 2

}
Daniel Dietrich
  • 2,262
  • 20
  • 25