kmizuの日記

プログラミングや形式言語に関係のあることを書いたり書かなかったり。

Scalaに関するよくある誤解(1) - 最後の処理の値が返り値になるのでreturnは不要

Scala 2.10.0 M3試してみる記事はいったんおいといて、前からよく見かけるScala(に限った話でもないですが)に関する誤解(とも言い切れないですが)について少し書いてみます。

Scalaで以下のようなコードがあったとき、

def add(x: Int, y: Int): Int = {
  return x + y
}

「Scalaでは最後の処理の値が返り値になるので、returnは不要」であるため、

def add(x: Int, y: Int): Int = {
   x + y
}

のように書けるのだ、という説明をよく見かけます。

しかし、この説明は正しくありません。「最後の処理」といいますが、それは、一体「何の」最後の処理なのでしょうか。

この説明の問題を理解するには、Scalaが「式」ベースの言語である事を理解する必要があります。まず、Scalaのメソッド定義の一般形は

def aMethod(arg: Int): Int = body

です。

def aMethod(arg: Int): Int = {
  stmt1
  stmt2
  ...
  stmtN
}

は、では*ありません*。このとき、bodyは(Int型になる)任意の式です。

Javaではメソッド宣言にはブロックが必須ですが、Scalaにおけるブロック({})は単なる式の一つでしかありません。そして、({})は、

{ expr1; expr2; ... exprN }

という形式を取り、exprの列を前から順番に評価し、exprNの評価結果がブロックの評価結果になります。

ここで、

def add(x: Int, y: Int): Int = {
   x + y
}

というコードに戻ります。=の右辺は単なる式であり、{}も式の種類の一つです。そして、{}はその中の式の列の最後の評価結果が{}の値になります。その結果、{ x + y }の評価結果がx+yになるというだけの事なのです。

Javaユーザに対する説明として、「returnを省略できる」という説明をするのは悪くありませんが、言語としてのScalaは、returnが無いのが通常の形式で、returnを付ける場合が特別だという事は、ある程度Scalaに慣れたユーザは念頭に置いても良いと思います。

よくある誤解といいつつ、大したことの無い話でしたが、ふと思い立って書いてみました。ではでは、また。