¿La prioridad / prioridad del operador de flecha (->) es la más baja, o la prioridad de la asignación / asignación combinada es la más baja?

18

JLS :

El operador de precedencia más baja es la flecha de una expresión lambda (->) , seguida de los operadores de asignación.

¿Seguido en qué dirección (prioridad creciente, prioridad decreciente)? - "seguido" significa que la asignación tiene mayor o menor prioridad (con respecto al operador de flecha)? Supongo que, en aumento, porque "más bajo" (para flecha) significa absolutamente más bajo.

Según tengo entendido, la flecha (->) debe estar en la parte inferior de esta tabla de precedencia de operadores de Princeton (que está debajo de todos los operadores de asignación), por lo tanto, la flecha (->) tiene 0 (cero) Nivel de prioridad (según esa tabla).

¿Estoy correcto en mi entendimiento?

ExamTray parece decir que la prioridad de la flecha es al menos igual que la asignación ... Además, aclaró que la asociatividad de la flecha es Izquierda-> A-> Derecha (a diferencia de la asignación). No encontré ninguna cita de JLS para asociatividad de flecha.

Siempre solía pensar que la prioridad de asignación es principalmente más baja por una razón.

Código completo
fuente
55
The lowest precedence operator is the arrow of a lambda expression.
Kayaman
2
Sí, tu comprensión es correcta.
Eran
44
Si ->es el bajo est , operadores de asignación no pueden tener baja er precedencia.
Andy Turner
IntFunction fo = a->b->a-b; // in test Implica prioridad / asociatividad de -> en general. Así que decidí aclarar -> lugar de precedencia / asociatividad en toda la tabla de precedencia / asociatividad porque me sentí inseguro al respecto.
Código completo el
1
@glglgl tu ejemplo de IntUnaryOperator op; op = x -> x;es interesante. ¿Quizás (op = x) -> xno se considera porque op = xno es una instancia válida de la LambdaParametersproducción?
Andy Turner el

Respuestas:

13

Tenga en cuenta la oración que precede al texto JLS citado :

La precedencia entre operadores se gestiona mediante una jerarquía de producciones gramaticales.

La gramática del lenguaje Java determina qué construcciones son posibles e implícitamente, la precedencia del operador.

Incluso la tabla princeton que has vinculado estados:

No hay una tabla de precedencia de operador explícito en la Especificación del lenguaje Java. Diferentes tablas en la web y en los libros de texto no están de acuerdo en algunos aspectos menores.

Por lo tanto, la gramática del lenguaje Java no permite expresiones lambda a la izquierda de un operador de asignación y tampoco permite asignaciones a la izquierda del ->. Por lo tanto, no hay ambigüedad entre estos operadores posibles y la regla de precedencia, aunque explícitamente establecida en el JLS, deja de tener sentido.

Esto permite compilar, por ejemplo, tal gema, sin ambigüedad:

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

Primero, expliquemos el problema práctico aquí.

Asumiendo que tienes una definición como

IntUnaryOperator op;

Lo siguiente se acepta sintácticamente y funciona como se espera:

op = x -> x;

Es decir, tenemos una función de identidad intasignada a la opvariable. Pero si =tuviera una mayor prioridad, esperaríamos que Java interprete esto como

(op = x) -> x;

Lo cual no es sintácticamente válido, por lo tanto, debería ser un error de compilación. Por lo tanto, la asignación no tiene, en la práctica, mayor precedencia que la flecha.

Pero lo siguiente también está bien (supongamos que tes una variable de clase / instancia de tipo int):

op = x -> t = x;

Esto compila, y la función, si se aplica, asigna el valor del operando ty también lo devuelve.

Esto significa que la flecha no tiene mayor prioridad que la asignación t = x. De lo contrario, se habría interpretado como

op = ( x -> t ) = x

y claramente, esto no es lo que pasa.

Entonces parece que las operaciones tienen la misma precedencia. Lo que es más, que son asociativos correctos. Esto está implícito en la gramática del capítulo 19 de JLS :

Expression:
  LambdaExpression
  AssignmentExpression

LambdaExpression:
  LambdaParameters -> LambdaBody

...

LambdaBody:
  Expression
  Block

Entonces, el lado derecho del cuerpo lambda nos devuelve Expression, lo que significa que podemos tener una lambda (de mayor prioridad) dentro o una asignación (de mayor prioridad). Lo que quiero decir con "mayor prioridad" es que cuanto más profundice en las reglas de producción, antes se evaluará la expresión.

Lo mismo es cierto para el operador de asignación:

AssignmentExpression:
  ConditionalExpression
  Assignment

Assignment:
  LeftHandSide AssignmentOperator Expression

Una vez más, el lado derecho de la tarea nos devuelve Expression, para que podamos tener una expresión lambda o una tarea allí.

Entonces, en lugar de confiar en el texto de JLS, la gramática nos da una descripción bien definida de la situación.

RealSkeptic
fuente