Die Priorität / Priorität des Pfeiloperators (->) ist am niedrigsten oder die Priorität der Zuweisung / kombinierten Zuweisung ist am niedrigsten?

18

JLS :

Der Operator mit der niedrigsten Priorität ist der Pfeil eines Lambda-Ausdrucks (->) , gefolgt von den Zuweisungsoperatoren.

In welche Richtung verfolgt (Priorität erhöhen, Priorität verringern)? - "gefolgt" bedeutet, dass die Zuweisung eine höhere oder niedrigere Priorität hat (in Bezug auf den Pfeiloperator)? Ich denke, in zunehmendem Maße, weil "niedrigste" (für Pfeil) absolut niedrigste bedeutet.

Soweit ich weiß, sollte sich der Pfeil (->) ganz unten in dieser Prioritäts-Tabelle für Princeton- Operatoren befinden (dh unter allen Zuweisungsoperatoren), daher sollte der Pfeil (->) die Prioritätsstufe 0 (Null) haben (gemäß dieser Tabelle).

Bin ich in meinem Verständnis richtig?

ExamTray scheint zu sagen, dass die Pfeilpriorität mindestens der Zuweisung entspricht ... Außerdem wurde klargestellt, dass die Pfeilassoziativität Links-> Nach-> Rechts ist (im Gegensatz zur Zuweisung). Ich habe kein JLS-Zitat für Pfeilassoziativität gefunden.

Ich habe immer gedacht, dass die Zuweisungspriorität aus einem bestimmten Grund hauptsächlich am niedrigsten ist.

Code abgeschlossen
quelle
5
The lowest precedence operator is the arrow of a lambda expression.
Kayaman
2
Ja, dein Verständnis ist richtig.
Eran
4
Wenn ->die niedrig ist est , Zuweisungsoperator können nicht niedrig haben sie Vorrang.
Andy Turner
IntFunction fo = a->b->a-b; // in test Impliziert Priorität / Assoziativität von -> im Allgemeinen. Deshalb habe ich mich entschlossen zu klären -> Vorrang / Assoziativitätsplatz in der gesamten Vorrang- / Assoziativitätstabelle, weil ich mich nicht sicher war.
Code abgeschlossen
1
@glglgl dein Beispiel IntUnaryOperator op; op = x -> x;ist interessant. Vielleicht (op = x) -> xwird nicht berücksichtigt, weil op = xkeine gültige Instanz der LambdaParametersProduktion ist?
Andy Turner

Antworten:

13

Beachten Sie den Satz vor dem zitierten JLS-Text :

Der Vorrang unter den Operatoren wird durch eine Hierarchie von Grammatikproduktionen verwaltet.

Die Grammatik der Java-Sprache bestimmt, welche Konstrukte möglich sind, und implizit die Priorität des Operators.

Sogar die von Ihnen verknüpfte Princeton-Tabelle lautet:

In der Java-Sprachspezifikation gibt es keine explizite Operator-Prioritätstabelle. Verschiedene Tabellen im Web und in Lehrbüchern stimmen in einigen geringfügigen Punkten nicht überein.

Die Grammatik der Java-Sprache erlaubt also keine Lambda-Ausdrücke links von einem Zuweisungsoperator und erlaubt auch keine Zuweisungen links von ->. Es ist also keine Mehrdeutigkeit zwischen diesen Operatoren möglich, und die Vorrangregel wird, obwohl sie im JLS ausdrücklich angegeben ist, bedeutungslos.

Dies ermöglicht das Kompilieren, z. B. eines solchen Edelsteins, ohne Mehrdeutigkeit:

static Consumer<String> C;
static String S;
public static void main(String[] args)
{
  Runnable r;
  r = () -> C = s -> S = s;
}
Holger
quelle
10

Lassen Sie uns zunächst das praktische Problem hier erläutern.

Angenommen, Sie haben eine Definition wie

IntUnaryOperator op;

Folgendes wird syntaktisch akzeptiert und funktioniert wie erwartet:

op = x -> x;

Das heißt, wir haben der Identität eine Identitätsfunktion intzugewiesen op. Wenn =wir jedoch eine höhere Priorität hätten, würden wir erwarten, dass Java dies als interpretiert

(op = x) -> x;

Was syntaktisch nicht gültig ist, sollte daher ein Kompilierungsfehler sein. Daher hat die Zuweisung in der Praxis keine höhere Priorität als der Pfeil.

Das Folgende ist aber auch in Ordnung (vorausgesetzt, es thandelt sich um eine Klassen- / Instanzvariable vom Typ int):

op = x -> t = x;

Dies wird kompiliert, und die Funktion weist, falls angewendet, den Wert des Operanden zu tund gibt ihn auch zurück.

Dies bedeutet, dass der Pfeil keine höhere Priorität als die Zuweisung hat t = x. Andernfalls wäre es interpretiert worden als

op = ( x -> t ) = x

und klar, das ist nicht was passiert.

Es scheint also, dass die Operationen den gleichen Vorrang haben. Was mehr ist, dass sie rechtsassoziativ sind. Dies geht aus der Grammatik in JLS Kapitel 19 hervor :

Expression:
  LambdaExpression
  AssignmentExpression

LambdaExpression:
  LambdaParameters -> LambdaBody

...

LambdaBody:
  Expression
  Block

Die rechte Seite des Lambda-Körpers bringt uns zurück Expression, was bedeutet, dass wir entweder ein Lambda (mit höherer Priorität) oder eine Zuordnung (mit höherer Priorität) darin haben können. Was ich unter "höherer Priorität" verstehe, ist, dass der Ausdruck umso früher ausgewertet wird, je tiefer Sie durch die Produktionsregeln gehen.

Gleiches gilt für den Zuweisungsoperator:

AssignmentExpression:
  ConditionalExpression
  Assignment

Assignment:
  LeftHandSide AssignmentOperator Expression

Noch einmal, die rechte Seite der Aufgabe wirft uns zurück Expression, so dass wir dort einen Lambda-Ausdruck oder eine Aufgabe haben können.

Anstatt sich auf den JLS-Text zu verlassen, gibt uns die Grammatik eine genau definierte Beschreibung der Situation.

RealSkeptic
quelle