Ich glaube, Mr. Sobral's Antwort ist falsch. Die eigentlichen Regeln finden Sie in Scala Language Reference, Abschnitt 6.23, Unterüberschrift "Platzhaltersyntax für anonyme Funktionen."
Die einzige Regel ist, dass der innerste Ausdruck, der den Unterstrich richtig enthält, den Umfang der anonymen Funktion definiert. Das bedeutet, dass die ersten beiden Regeln von Herrn Sobral korrekt sind, weil ein Methodenaufruf ein Ausdruck ist und die Klammerung eines Ausdrucks seine Bedeutung nicht ändert. Aber die dritte Regel ist das Gegenteil der Wahrheit: alle anderen Dinge sind gleich, der kleinste Ausdruck, der Sinn macht, wird verwendet.
Leider ist meine Erklärung für das Verhalten, das Herr Laskowski für sein erstes Beispiel beobachtet hat, etwas umständlich und spekulativ. Wenn
ist in der Scala Read-Eval-Print-Schleife eingegeben.Die Fehlermeldung lautet:
error: type mismatch;
found : Unit
required: Int => ?
List(1,2,3) foreach println(_:Int)
^
Wenn Sie variieren das Beispiel ein kleines bisschen:
List(1,2,3).foreach println(_:Int)
die Fehlermeldung leichter ist, einen Sinn zu geben -
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)
^
Um zu verstehen, was ein etwas besser, rufen Sie scala
so: scala -Xprint:parser
, die, nach jedem Ausdruck vom Benutzer eingegeben wird, bewirkt, dass der Ausdruck, der durch den Parser ausgedruckt wird, gedruckt wird. (Zusammen mit einer Menge Müll, die ich weglassen.) Für Laskowski erstes Beispiel wird der Ausdruck durch den Parser zu verstehen ist
((x$1: Int) => List(1, 2, 3).foreach(println((x$1: Int))))
Für das zweite Beispiel der Version des Parsers ist
((x$1: Int) => List(1, 2, 3).foreach.println((x$1: Int)))
Offensichtlich wird die Bereichsregel angewendet, bevor die Ausdrucksstruktur vollständig ausgearbeitet wurde. In beiden Fällen rät der Parser, dass der kleinste Ausdruck bei List beginnt, auch wenn die Parens erst eingefügt werden, wenn sie nicht mehr wahr sind. Im zweiten Beispiel wird zusätzlich zu dieser Annahme davon ausgegangen, dass println
ein Bezeichner ist. foreach println
ist eine Kette von Methoden, von denen die erste keine Argumente hat. Der Fehler bei foreach
wird dann vor dem Fehler bei println
abgefangen und verdeckt. Der Fehler bei println
ist, dass das Ergebnis Unit lautet und foreach
eine Funktion erfordert. Sobald Sie den Syntaxbaum sehen, ist es leicht zu sehen, dass dies korrekt ist, aber es ist mir nicht klar, warum der Syntaxbaum das ist, was er ist.