javalambdasyntax

Clarity on Java Lambda Syntax


From my understanding, this is a single statement in Java:

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

If that is the case, why is this a syntax error:

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();

And this is not a syntax error.

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();

Solution

  • this is a single statement in Java

    Yes. Keyword, statement. If you use braceless lambda syntax, the one thing to the right of the arrow must be an expression. That while statement isn't one, so it isn't legal. See JLS §15.27.

    Where you may be confused, is this somewhat odd concept in java called 'expression statements'.

    Some things in java are both a statement and an expression (or, rather, they are expressions that can be turned into a statement simply by adding a semi-colon). The list is fairly small. The most obvious ones:

    Methods that return void are a particularly weird kind of expression statement. Whilst they are expressions, using them in any way other than as a statement is a compiler error due to the void part of it.

    Point is, all the expression statements, even void-returning methods, are still considered expressions, and therefore can form the business end of a lambda expression without braces.

    while is not a expression statement; it's just a statement. Therefore, cannot appear to the right of that arrow (at least, not without braces).

    If you want real weirdness, check out switch. Which isn't quite a statement expression, but can be used as an expression, or as a statement (in recent versions of java, at least).