Pierwszeństwo / priorytet operatora strzałki (->) jest najniższy, czy priorytet przypisania / przypisania łączonego jest najniższy?

18

JLS :

Operatorem o najniższym priorytecie jest strzałka wyrażenia lambda (->) , po której następują operatory przypisania.

Podążano w jakim kierunku (zwiększenie priorytetu, zmniejszenie priorytetu)? - „obserwowane” oznacza przypisanie o wyższym priorytecie lub niższym priorytecie (w odniesieniu do operatora strzałki)? Wydaje mi się, że rośnie, ponieważ „najniższy” (dla strzałki) oznacza absolutnie najniższy.

Jak rozumiem, strzałka (->) powinna znajdować się na samym dole tabeli pierwszeństwa operatora Princeton (czyli poniżej wszystkich operatorów przypisania), a zatem strzałka (->) ma poziom priorytetu 0 (zero) (zgodnie z tą tabelą).

Czy mam rację w moim rozumieniu?

ExamTray wydaje się mówić, że priorytet strzały jest co najmniej taki sam jak przypisanie ... Plus wyjaśnił, że skojarzenie strzały jest Lewo-> To-> Prawo (w przeciwieństwie do przypisania). Nie znalazłem żadnego cytatu JLS dotyczącego asocjatywności strzał.

Zawsze uważałem, że z jakiegoś powodu priorytet przydziału jest zasadniczo najniższy.

Kod ukończony
źródło
5
The lowest precedence operator is the arrow of a lambda expression.
Kayaman
2
Tak, twoje zrozumienie jest poprawne.
Eran
4
Jeśli ->jest niska est , operatory przypisania nie może mieć niską er pierwszeństwo.
Andy Turner
IntFunction fo = a->b->a-b; // in test Implikuje priorytet / powiązanie -> ogólnie. Postanowiłem więc wyjaśnić -> miejsce pierwszeństwa / skojarzenia w całej tabeli pierwszeństwa / skojarzenia, ponieważ czułem się niepewnie.
Kod Ukończono
1
@glglgl twój przykład IntUnaryOperator op; op = x -> x;jest interesujący. Być może (op = x) -> xnie jest brany pod uwagę, ponieważ op = xnie jest prawidłową instancją LambdaParametersprodukcji?
Andy Turner

Odpowiedzi:

13

Zwróć uwagę na zdanie poprzedzające cytowany tekst JLS :

Priorytetem wśród operatorów zarządza hierarchia produkcji gramatycznych.

Gramatyka języka Java określa, które konstrukcje są możliwe i domyślnie pierwszeństwo operatora.

Nawet stół Princeton , który połączyłeś, stwierdza:

W specyfikacji języka Java nie ma jawnej tabeli pierwszeństwa operatorów. Różne tabele w Internecie i w podręcznikach nie zgadzają się w pewien drobny sposób.

Tak więc gramatyka języka Java nie pozwala na wyrażenia lambda po lewej stronie operatora przypisania i podobnie nie pozwala na przypisania po lewej stronie ->. Nie ma więc żadnej dwuznaczności między tymi operatorami, a zasada pierwszeństwa, choć wyraźnie określona w JLS, staje się bez znaczenia.

Pozwala to skompilować, np. Taki klejnot, bez dwuznaczności:

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

Najpierw wyjaśnijmy tutaj praktyczny problem.

Zakładając, że masz taką definicję

IntUnaryOperator op;

Następujące elementy są akceptowane składniowo i działają zgodnie z oczekiwaniami:

op = x -> x;

Oznacza to, że mamy funkcję tożsamości intprzypisaną do opzmiennej. Ale gdyby =miał wyższy priorytet, spodziewalibyśmy się, że Java to zinterpretuje

(op = x) -> x;

Który nie jest poprawny pod względem składniowym, powinien więc wystąpić błąd kompilacji. Dlatego zadanie nie ma w praktyce większego pierwszeństwa niż strzałka.

Ale poniższe są również OK (załóżmy, że tjest to zmienna typu klasa / instancja int):

op = x -> t = x;

To się kompiluje, a funkcja, jeśli zastosowana, przypisuje wartość argumentu do, ta także zwraca ją.

Oznacza to, że strzałka nie ma wyższego pierwszeństwa niż przypisanie t = x. W przeciwnym razie byłoby to interpretowane jako

op = ( x -> t ) = x

i oczywiście nie dzieje się tak.

Wygląda więc na to, że operacje mają równy priorytet. Co więcej, są one odpowiednio skojarzone. Sugeruje to gramatyka rozdziału 19 JLS :

Expression:
  LambdaExpression
  AssignmentExpression

LambdaExpression:
  LambdaParameters -> LambdaBody

...

LambdaBody:
  Expression
  Block

Tak więc prawa strona ciała lambda prowadzi nas z powrotem do tego Expression, co oznacza, że ​​możemy mieć w sobie lambda (o wyższym priorytecie) lub przypisanie (o wyższym priorytecie). Rozumiem przez „wyższy priorytet”, że im głębiej przejdziesz przez reguły produkcji, tym wcześniej wyrażenie zostanie ocenione.

To samo dotyczy operatora przypisania:

AssignmentExpression:
  ConditionalExpression
  Assignment

Assignment:
  LeftHandSide AssignmentOperator Expression

Po raz kolejny prawa strona zadania przenosi nas z powrotem Expression, abyśmy mogli otrzymać wyrażenie lambda lub zadanie.

Zamiast więc polegać na tekście JLS, gramatyka daje nam dobrze zdefiniowany opis sytuacji.

RealSkeptic
źródło