kmizuの日記

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

_ と _ の違い

意味不明なタイトルですね。このエントリの目的は、二つの似た_の使い方が全く異なる意味を持っていることを認識してもらうことです。

最初に結論を言います。Scalaの式中における

obj.method _

という使い方(Method Values)と

obj.method(_)

という使い方(Placeholder Syntax for Anonymous Functions)*1

は全く異なるものです。似た場面で使えることがありますが、展開/コンパイル結果は一般に異なります。これが一番重要な点です*2

両者の区別は簡単で、

obj.method _

のように、メソッド名の後に一個以上のスペースに加えて、単独で_が現れたら、間違いなくMethod Valuesです(:の後に型注釈が付くこともありますが、それはオフトピックなのでおいておきます)。
それ以外のケースは基本的にPlaceholder Syntax for Anonymous Functionsです。

この二つのよく似た構文ですが、実際に展開されるタイミングという点で決定的な違いがあります。

Method Valuesは、型チェック(の後)のタイミングで作用し、メソッドを無名関数でラップしてオブジェクト化するための処理をはさみ込みます。Method Valuesは、対象となる式がメソッド型または名前渡しパラメータでなければいけないため、対象となる式の型が条件を満たしているかどうかのチェックが行われ、チェックを通った後に展開が行われます*3

Placholder Syntax for Anonymous Functionsは、構文解析のタイミングで作用し、式中に現れる_を無名関数の仮引数の参照に置き換えて、無名関数に変換するための処理をはさみ込みます。型チェッカは展開結果に全く関係ありません。Placeholder Syntax for Anonymous FunctionsのルールはScala Language Specification p.94に記述されていますが、型に関して言及していないことがわかります。もちろん、その後に型チェックが行われますが、あくまで展開後の無名関数に対して型チェックが行われるのであって、Placeholder Syntax for Anonymous Functionsを使った式に対して型チェックが行われるわけではないことに注意してください。

即興で記事を書いたのでイマイチまとまりが悪いですね。とりあえず参考程度に。

*1:私が主にプレースホルダー構文と呼んでいるもの

*2:ちなみに、全く違う意味を持つものに同じ_という記号を割り当てたのはScalaの仕様が悪いと思います

*3:Method Valuesに関しては、Scala Language Specification p.80を参照してください