Flèche (->) la priorité / priorité de l'opérateur est la plus faible, ou la priorité de l'affectation / affectation combinée est la plus faible?

18

JLS :

L' opérateur de priorité la plus faible est la flèche d'une expression lambda (->) , suivie des opérateurs d'affectation.

Suivi dans quelle direction (priorité croissante, priorité décroissante)? - «suivi» signifie que l'affectation a une priorité plus élevée ou une priorité plus faible (par rapport à l'opérateur de la flèche)? Je suppose, en augmentant, parce que "le plus bas" (pour la flèche) signifie absolument le plus bas.

Si je comprends bien, la flèche (->) devrait être tout en bas de ce tableau de priorité des opérateurs de Princeton (qui est en dessous de tous les opérateurs d'affectation), donc la flèche (->) ayant un niveau de priorité 0 (zéro) (selon ce tableau).

Ai-je raison de comprendre?

ExamTray semble dire que la priorité des flèches est au moins la même que celle des affectations ... Plus a précisé que l'associativité des flèches est Gauche-> À-> Droite (contrairement à l'affectation). Je n'ai trouvé aucune citation JLS pour l'associativité des flèches.

J'ai toujours pensé que la priorité d'affectation est principalement la plus basse pour une raison.

Code terminé
la source
5
The lowest precedence operator is the arrow of a lambda expression.
Kayaman
2
Oui, votre compréhension est correcte.
Eran
4
Si ->le faible EST , les opérateurs d'affectation ne peuvent pas avoir faible er priorité.
Andy Turner
IntFunction fo = a->b->a-b; // in test Implique la priorité / associativité de -> en général. J'ai donc décidé de clarifier -> priorité / associativité place dans l'ensemble du tableau de priorité / associativité parce que je n'étais pas sûr de cela.
Code terminé
1
@glglgl votre exemple IntUnaryOperator op; op = x -> x;est intéressant. Peut (op = x) -> x- être n'est-il pas pris en compte car op = xn'est-ce pas une instance valide de la LambdaParametersproduction?
Andy Turner

Réponses:

13

Notez la phrase précédant le texte JLS cité :

La priorité parmi les opérateurs est gérée par une hiérarchie de productions grammaticales.

La grammaire du langage Java détermine quelles constructions sont possibles et implicitement, la priorité de l'opérateur.

Même la table de Princeton que vous avez liée aux États:

Il n'y a pas de table de priorité d'opérateur explicite dans la spécification du langage Java. Différents tableaux sur le Web et dans les manuels scolaires sont en désaccord de façon mineure.

Ainsi, la grammaire du langage Java n'autorise pas les expressions lambda à gauche d'un opérateur d'affectation et, de même, n'autorise pas les affectations à gauche de l'opérateur ->. Il n'y a donc aucune ambiguïté possible entre ces opérateurs et la règle de priorité, bien qu'explicitement énoncée dans le JLS, perd tout son sens.

Cela permet de compiler, par exemple un tel bijou, sans ambiguïté:

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

Tout d'abord, expliquons le problème pratique ici.

En supposant que vous ayez une définition comme

IntUnaryOperator op;

La syntaxe suivante est acceptée et fonctionne comme prévu:

op = x -> x;

Autrement dit, nous avons une fonction d'identité sur intaffectée à la opvariable. Mais s'il =avait une priorité plus élevée, nous nous attendrions à ce que Java l'interprète comme

(op = x) -> x;

Ce qui n'est pas syntaxiquement valide, devrait donc être une erreur de compilation. Par conséquent, l'affectation n'a pas, en pratique, une priorité plus élevée que la flèche.

Mais ce qui suit est également OK (supposons qu'il ts'agit d'une variable de classe / instance de type int):

op = x -> t = x;

Cela compile et la fonction, si elle est appliquée, affecte la valeur de l'opérande à tet la renvoie également.

Cela signifie que la flèche n'a pas une priorité plus élevée que l'affectation t = x. Sinon, il aurait été interprété comme

op = ( x -> t ) = x

et clairement, ce n'est pas ce qui se passe.

Il semble donc que les opérations aient la même priorité. De plus, ils sont associatifs à droite. Cela ressort de la grammaire du chapitre 19 de JLS :

Expression:
  LambdaExpression
  AssignmentExpression

LambdaExpression:
  LambdaParameters -> LambdaBody

...

LambdaBody:
  Expression
  Block

Donc, le côté droit du corps lambda nous ramène à Expression, ce qui signifie que nous pouvons avoir soit un lambda (de priorité plus élevée) à l'intérieur, soit une affectation (de priorité plus élevée). Ce que je veux dire par "priorité plus élevée", c'est que plus vous approfondissez les règles de production, plus tôt l'expression sera évaluée.

Il en va de même pour l'opérateur d'affectation:

AssignmentExpression:
  ConditionalExpression
  Assignment

Assignment:
  LeftHandSide AssignmentOperator Expression

Encore une fois, le côté droit de l'affectation nous renvoie à Expression, afin que nous puissions avoir une expression lambda ou une affectation là-bas.

Ainsi, plutôt que de s'appuyer sur le texte JLS, la grammaire nous donne une description bien définie de la situation.

RealSkeptic
la source