Ясность синтаксиса Java Lambda

Насколько я понимаю, это один оператор в Java:

while((x % p == 0l) && (x > p)) x /= p;

Если это так, то почему это синтаксическая ошибка:

final AtomicLong subtotal = new AtomicLong(limit);

final long maxPrimeFactor = primeStream.takeWhile(p -> p * p <= limit)
                                       .filter(p -> subtotal.get() % p == 0)
                                       .peek(p -> while((subtotal.get() % p == 0) && (subtotal.get() > p)) subtotal.set(subtotal.get() / p)) // Syntax error here.
                                       .dropWhile(p -> p != subtotal.get())
                                       .findFirst()
                                       .getAsLong();

И это не синтаксическая ошибка.

final AtomicLong subtotal = new AtomicLong(limit);

final long maxPrimeFactor = primeStream.takeWhile(p -> p * p <= limit)
                                       .filter(p -> subtotal.get() % p == 0)
                                       .peek(p -> { while((subtotal.get() % p == 0) && (subtotal.get() > p)) subtotal.set(subtotal.get() / p)); } // No syntax error here.
                                       .dropWhile(p -> p != subtotal.get())
                                       .findFirst()
                                       .getAsLong();

Примечание. Ответы на отмеченный дубликат не дали мне ответа на вопрос. Принятый ответ сделал.

Покажите нам полный текст ошибки.

talex 21.07.2024 19:23

Цикл while с телом — это не один оператор.

Elliott Frisch 21.07.2024 19:28

@ElliottFrisch технически это одно утверждение. Некоторые операторы могут содержать внутри другие операторы.

talex 21.07.2024 19:42

В частности Оператор while

talex 21.07.2024 19:46

@talex Возможно. Он дает разбивку как WhileStatement: while ( Expression ) Statement, что означает, что это два оператора в одном, как вы сказали, но Expression может завершиться, и в этом случае подоператор не выполняется. Таким образом, если они представляют собой одно утверждение, оно не является атомарным.

Elliott Frisch 21.07.2024 19:47

Он называется WhileStatement. Что еще тебе нужно? Какое определение высказывания вы используете?

talex 21.07.2024 19:50
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
7
79
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

p->something ожидайте, что something будет выражением, а не утверждением.

p->{something} ожидайте, что something будет утверждением или, точнее, списком утверждений.

См.: 15.27. Лямбда-выражения

Конкретно 15.27.2. Лямбда-тело:

LambdaBody:
   Expression
   Block 

Block:
   { [BlockStatements] } 
Ответ принят как подходящий

это один оператор в Java

Да. Ключевое слово, утверждение. Если вы используете лямбда-синтаксис без скобок, то справа от стрелки должно быть выражение. Это while утверждение не является таковым, поэтому оно незаконно. См. JLS §15.27.

Вас может смутить это несколько странное понятие в Java, называемое «операторы выражения».

Некоторые вещи в Java являются одновременно оператором и выражением (или, скорее, это выражения, которые можно превратить в оператор, просто добавив точку с запятой). Список довольно небольшой. Самые очевидные из них:

  • вызовы методов.
  • вызовы конструктора (немного странно игнорировать то, что вы сделали, но это разрешено).
  • операторы, которые мутируют. x++ например. Или x = 5 (это выражение! int x = 10; int y = x = 15; является допустимым Java, и в результате x и y равны '15'. Результатом выражения присваивания является значение присвоенного объекта).

Методы, возвращающие void, представляют собой особенно странный вид выражений. Хотя это выражения, использование их каким-либо иным образом, кроме как в качестве оператора, является ошибкой компилятора из-за его части void.

Дело в том, что все операторы выражений, даже методы, возвращающие void, по-прежнему считаются выражениями и, следовательно, могут образовывать бизнес-конец лямбда-выражения без фигурных скобок.

while не является выражением; это просто заявление. Поэтому он не может появиться справа от этой стрелки (по крайней мере, без фигурных скобок).

Если хотите настоящих странностей, загляните switch. Это не совсем операторное выражение, но его можно использовать как выражение или как оператор (по крайней мере, в последних версиях Java).

«Некоторые вещи в Java являются одновременно утверждением и выражением», что неверно. foo() — выражение, foo(); — утверждение.

talex 21.07.2024 21:24

Не существует такого понятия, как «выражение утверждения». Вы, вероятно, имеете в виду «выражение-выражение».

talex 21.07.2024 21:26

Выражение переключателя и оператор переключения имеют разный синтаксис,

talex 21.07.2024 21:29

@talex Хотите уточнить? Я хотел бы увидеть пример каждого.

Tripp Kinetics 28.07.2024 16:16

@TrippKinetics возможно, что в выражениях используется case FOO -> вместо case FOO:, но сам оракул также называет обозначение стрелки «операторами переключения», и вы можете использовать их в переключателях операторов. Такое ощущение, что компания Talex взяла на себя педантическую миссию, и они перегнули палку.

rzwitserloot 28.07.2024 20:26

@rzwitserloot достаточно справедливо. Я предполагаю, что выражение переключения можно использовать в качестве оператора, потому что это оператор-выражение, но если оракул видит это по-другому, то я ошибаюсь. И да, вы правильно угадали мою миссию :)

talex 29.07.2024 07:59

Другие вопросы по теме

В GCC внутри лямбды я могу получить переменную constexpr из лямбды шаблона, отличного от constexpr, но не в Visual C++
Получить переменную constexpr из лямбда-функции можно, но компиляция завершается неудачей (Visual C++) и штрафом (gcc), когда такой оператор находится в новой лямбда-функции
Каков тип шаблонной лямбды?
Тернарный оператор не работает внутри функции Lambda Ruby
Создание универсального селектора/установщика свойств на C#, если вы знаете тип только во время выполнения
Как преобразовать лямбда-функцию в другую, используя кортеж параметров
Если лямбда объявлена ​​внутри аргумента по умолчанию, отличается ли она для каждого сайта вызова?
Возврат константной ссылки из лямбды, хранящейся как std::function segfaults
Подсчитайте количество аргументов в общей лямбде
Как вызвать функцию из функции в классе, который вызывается с помощью кнопки с лямбдой в Python3x?