Стрелка (->) приоритет оператора / приоритет самый низкий, или приоритет назначения / комбинированное назначение самый низкий?

18

JLS :

Оператор с наименьшим приоритетом - стрелка лямбда-выражения (->) , за которой следуют операторы присваивания.

В каком направлении следовали (увеличение приоритета, уменьшение приоритета)? - «сопровождается» означает, что присвоение имеет более высокий или более низкий приоритет (по отношению к оператору стрелки)? Я думаю, при увеличении, потому что «низший» (для стрелки) означает абсолютно низший.

Как я понимаю, стрелка (->) должна находиться в самом низу этой таблицы приоритетов операторов Принстона (то есть ниже всех операторов присваивания), поэтому стрелка (->) имеет 0 (нулевой) уровень приоритета (согласно этой таблице).

Правильно ли я понимаю?

ExamTray, кажется, говорит, что приоритет стрелки, по крайней мере, такой же, как и при назначении ... Плюс уточнено, что ассоциативность стрелки имеет вид Left-> To-> Right (в отличие от назначения). Я не нашел никакой цитаты JLS для ассоциативности стрелы.

Раньше я всегда думал, что приоритет назначения является наименьшим по определенной причине.

Код завершен
источник
5
The lowest precedence operator is the arrow of a lambda expression.
Каяман
2
Да, ваше понимание верно.
Эран
4
Если ->это низкий Эст , операторы присваивания не могут иметь низкий эр приоритет.
Энди Тернер
IntFunction fo = a->b->a-b; // in test Подразумевает приоритет / ассоциативность -> в целом. Поэтому я решил уточнить -> место приоритета / ассоциативности во всей таблице приоритетов / ассоциативности, потому что чувствовал себя неуверенно по этому поводу.
Код завершен
1
@glglgl ваш пример IntUnaryOperator op; op = x -> x;интересен. Возможно (op = x) -> x, не рассматривается, потому что op = xне является действительным экземпляром LambdaParametersпроизводства?
Энди Тернер

Ответы:

13

Обратите внимание на предложение, предшествующее цитируемому тексту JLS :

Приоритет среди операторов управляется иерархией грамматических произведений.

Грамматика языка Java определяет, какие конструкции возможны и неявно, приоритет оператора.

Даже таблица Принстона, которую вы связали, утверждает:

В Спецификации языка Java нет явной таблицы приоритетов операторов. Различные таблицы в Интернете и в учебниках расходятся во мнениях.

Таким образом, грамматика языка Java не допускает лямбда-выражений слева от оператора присваивания, а также не разрешает присваивания слева от оператора ->. Таким образом, нет никакой двусмысленности между этими возможными операторами, и правило приоритета, хотя оно явно указано в JLS, становится бессмысленным.

Это позволяет скомпилировать, например, такой драгоценный камень, без двусмысленности:

static Consumer<String> C;
static String S;
public static void main(String[] args)
{
  Runnable r;
  r = () -> C = s -> S = s;
}
Holger
источник
10

Сначала давайте объясним практическую проблему здесь.

Предполагая, что у вас есть определение, как

IntUnaryOperator op;

Следующее синтаксически принято, и работает как ожидалось:

op = x -> x;

То есть у нас есть функция тождественности на intприсвоенной opпеременной. Но если бы у нас =был более высокий приоритет, мы ожидали бы, что Java интерпретирует это как

(op = x) -> x;

Что не является синтаксически допустимым, поэтому должно быть ошибкой компиляции. Следовательно, на практике присвоение не имеет более высокого приоритета, чем стрелка.

Но следующее тоже нормально (предположим t, это переменная класса / экземпляра типа int):

op = x -> t = x;

Это компилирует, и функция, если применяется, присваивает значение операнда tи также возвращает его.

Это означает, что стрелка не имеет более высокого приоритета, чем назначение t = x. В противном случае это было бы интерпретировано как

op = ( x -> t ) = x

и ясно, что это не то, что происходит.

Таким образом, кажется, что операции имеют равный приоритет. Более того, они правы ассоциативны. Это подразумевается из грамматики в главе 19 JLS :

Expression:
  LambdaExpression
  AssignmentExpression

LambdaExpression:
  LambdaParameters -> LambdaBody

...

LambdaBody:
  Expression
  Block

Таким образом, правая сторона лямбда-тела возвращает нас назад Expression, что означает, что мы можем иметь либо (более высокий приоритет) лямбда внутри него, либо (более высокий приоритет) назначение в нем. Под «более высоким приоритетом» я подразумеваю, что чем глубже вы будете следовать правилам производства, тем раньше будет оцениваться выражение.

То же самое верно для оператора присваивания:

AssignmentExpression:
  ConditionalExpression
  Assignment

Assignment:
  LeftHandSide AssignmentOperator Expression

Еще раз, правая часть присваивания отбрасывает нас назад Expression, поэтому мы можем иметь там лямбда-выражение или присваивание.

Поэтому вместо того, чтобы полагаться на текст JLS, грамматика дает нам четкое описание ситуации.

RealSkeptic
источник