Search code examples
javagrammarboolean-logicshort-circuiting

Replacing an if statement with a disjunction


Just for fun, I was trying to replace:

if (set1.add(x) == false)
{
    set2.add(x);
}

with:

set1.add(x) || set2.add(x);

However, Eclipse complains:

Syntax error on token "||", invalid AssignmentOperator
The left-hand side of an assignment must be a variable

Could anybody shine some light onto these error messages? They don't make much sense to me.


Solution

  • There are a number of answers far, but I agree with Bohemian's answer that the most straightforward simplification (although it doesn't use ||) is this:

    if ( !set1.add(x) ) set2.add(x);
    

    That doesn't explain the error message though. Mustafa Genç comes closer on this, but I think it's worthwhile to look at the language specification here. exp1 || exp2 is an expression, and the problem here is that you're trying to use it in a context where a statement is expected. According to 14.8. Expression Statements, some kinds of expressions can be used where statements are expected by attaching a semicolon:

    14.8. Expression Statements

    Certain kinds of expressions may be used as statements by following them with semicolons.

    ExpressionStatement:
        StatementExpression ;
    
    StatementExpression:
        Assignment
        PreIncrementExpression
        PreDecrementExpression
        PostIncrementExpression
        PostDecrementExpression
        MethodInvocation
        ClassInstanceCreationExpression
    

    An expression statement is executed by evaluating the expression; if the expression has a value, the value is discarded.

    The reason that you can't do what you're trying to do, though, is that not every expression can be used as a statement. However, it does discuss some ways to work around this. From the same section of the specification (emphasis added):

    Unlike C and C++, the Java programming language allows only certain forms of expressions to be used as expression statements. Note that the Java programming language does not allow a "cast to void" - void is not a type - so the traditional C trick of writing an expression statement such as:

    (void)... ;  // incorrect!
    

    does not work. On the other hand, the Java programming language allows all the most useful kinds of expressions in expressions statements, and it does not require a method invocation used as an expression statement to invoke a void method, so such a trick is almost never needed. If a trick is needed, either an assignment statement (§15.26) or a local variable declaration statement (§14.4) can be used instead.

    This approach is what the first snipped in Reik Val's answer is using:

    boolean temp = set1.add(x) || set2.add(x);