ソブラルさんの答えは間違っていると思います。実際の規則は、Scala 言語リファレンスのセクション 6.23 のサブヘッド「無名関数のプレースホルダー構文」にあります。
唯一のルールは、アンダースコアを適切に含む最も内側の式が無名関数のスコープを定義することです。つまり、ソブラル氏の最初の 2 つの規則は正しいということです。なぜなら、メソッド呼び出しは式であり、式を括弧で囲んでもその意味は変わらないからです。しかし、3 番目の規則は真実の反対です。他のすべての条件が等しい場合、意味のある最小の式が使用されます。
残念ながら、Laskowski 氏が最初の例で観察した動作についての私の説明は、少し複雑で推測にすぎません。いつ
List(1,2,3) foreach println(_:Int)
Scala の read-eval-print ループで入力されます。エラーメッセージは次のとおりです。
error: type mismatch;
found : Unit
required: Int => ?
List(1,2,3) foreach println(_:Int)
^
例を少し変更すると、次のようになります。
List(1,2,3).foreach println(_:Int)
エラーメッセージは理解しやすい -
error: missing arguments for method foreach in class List;
follow this method with `_' if you want to treat it as a partially applied function
List(1,2,3).foreach println(_:Int)
^
物事をもう少しよく理解するには、scala
this:を呼び出します。scala -Xprint:parser
これは、ユーザーがすべての式を入力した後、パーサーによって肉付けされた式を出力します。(省略しますが、ゴミがたくさんあります。) Laskowski の最初の例では、パーサーが理解できる式は次のとおりです。
((x$1: Int) => List(1, 2, 3).foreach(println((x$1: Int))))
2 番目の例では、パーサーのバージョンは
((x$1: Int) => List(1, 2, 3).foreach.println((x$1: Int)))
明らかに、式の構造が完全に肉付けされる前に、スコープ ルールが適用されます。どちらの場合も、パーサーは最小の式が List で始まると推測しますが、括弧が挿入されるとそれは正しくなくなります。2 番目の例では、その仮定に加えて、println
は識別子でforeach println
あるため、 はメソッドのチェーンであり、最初のメソッドには引数がないと仮定しています。でのエラーforeach
は、エラーでのエラーの前に捕捉されprintln
、それをマスクします。のエラーprintln
は、その結果が Unit でforeach
あり、関数が必要であるということです。解析ツリーを見れば、これが正しいことは簡単にわかりますが、(私には) なぜ解析ツリーが何であるかは明確ではありません。