Pitfall 3:メソッド定義の=に要注意

これはScala初心者(=プログラミング初心者)が非常によくはまる罠です。特に、JavaユーザでScalaを始める人で、この落とし穴に落ちている人をしばしば見かけます。

Scalaでは、メソッド定義の形式は

def メソッド名(引数名:型名,...) : 型名 = 式

が基本です。: 型名の部分は、の型から通常推論されるので、省略可能です。ここで、Javaから来た人は、Javaの慣習に慣れているためか、しばしば

def foo() { //... }

のように書いてしまいます。

ここでコンパイルエラーになれば特に問題は無いのですが、Scalaでは、: 型名=が抜かされた場合、返り値の型をUnit、つまりJavaのvoidとみなします。そのため、メソッド定義の本体を確かに書いたはずなのに、何故か返り値を正しく受け取れない、という事態が発生します。たとえば、REPLで以下のように入力したとき、書いた人は1が出力される事を期待しているはずですが、実際は()というUnit型のオブジェクトが返ってきます。

scala> def badMethod() { 1 } badMethod: ()Unit scala> println(badMethod()) ()

この問題を避けるためには、メソッド定義の引数列の後は、必ず=を付ける、というのを徹底するしか方法はありません。実際のところ、この=を省略できるという仕様は、メリットはタイプ数が1文字節約できるだけですから、あまり良い仕様とは言えません。ともあれ、この仕様を使ったコードは既にたくさんありますから、今更削るわけにもいきません。最初に言った習慣を徹底するしか無いでしょう。幸いな事に、この問題は型に関する問題なので、コンパイル時に問題が起こっている事に大半の場合気づけるでしょう(上記のように出力しかしていない場合は別ですが)。