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


18

JLS :

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

Слідкуйте в якому напрямку (збільшуючи пріоритет, зменшуючи пріоритет)? - "наступний" означає, що призначення має більший пріоритет або нижчий пріоритет (стосовно оператора стрілки)? Гадаю, у збільшенні, тому що "найнижчий" (для стрілки) означає абсолютно найнижчий.

Як я розумію, стрілка (->) повинна знаходитися в самій нижній частині цієї таблиці пріоритетів операторів Прінстона (тобто нижче всіх операторів присвоєння), таким чином стрілка (->) має 0 (нульовий) рівень пріоритетності (відповідно до цієї таблиці).

Чи правильно я розумію?

Схоже, ExamTray каже, що пріоритет стрілки принаймні такий самий, як і призначення ... Плюс уточнив, що асоціативність стрілки - ліворуч-> до-> праворуч (на відміну від призначення). Я не знайшов жодної цитати 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;
}

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, граматика дає нам чітко визначений опис ситуації.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.