return省略のルール
Groovyではreturn文において、returnキーワードの省略ができます。たとえば
boolean even(n) { if (n % 2 == 0) { return true } else { return false; } }
はこうかけます。
boolean even(n) { if (n % 2 == 0) { true } else { false; } }
でも、こうは書けません。
int sum(n) { int sum = 0; while (n-- > 0) { sum += n; } // 「return sum」を省略することはできない。 }
whileの最後の回のループでの評価値がメソッドの戻り値としてreturnされるということはないです。「最後に評価した値がreturn値として用いられる」というルールではないからですね。
Groovyのreturnキーワード省略のルールは、こういうものです。
直後にメソッドから脱出することがわかっている場所での式文は、「return」キーワードを省略したreturn文だとみなす。
これは純粋に構文上のルールです。実際、上の1番目と2番目の例では生成されるバイトコードは同一です。
それに対して、3番目のコードは、
int sum(n) { int sum = 0; while (n-- > 0) { return sum += n; } }
の省略形と解釈されると困りますし、そう解釈されることはありません。
とはいうものの、eachなどのクロージャを引数に取る繰り返しメソッドは、返り値を持っていますので、
int sum(n) { int sum = 0; (1..n).each { sum += n } }
が期待するように動く可能性はあるわけです。つまり上では、
int sum(n) { int sum = 0; return (1..n).each { sum += n } }
のようにreturnが省略されているとみなされるので、eachメソッドの呼び出し結果を返すからです。でも残念ながら、現在のeachの実装は、評価したクロージャの値を返すようにはなっていないので、駄目です。以下のように自前で作ればOK。
def threeTimes(Closure clos){ clos.call() clos.call() return clos.call() // 3回実行し、最後の回の評価値を返す } def foo(n) { def sum = 0 threeTimes{ sum += n } // return不要 } assert foo(3) == 9