Search code examples
javakotlinlogical-operatorsoperator-precedencexor

Is XOR operator in Kotlin a feature or a bug?


I've been a Java Developer for many years and recently I've found something very suprising in Kotlin. In Java there is a rarely used logical operator ^ XOR but sometimes it's useful. For example: you can easly check if one and only one of two numbers is greater than zero.

With && AND operator and some variables a and b it looks like that:

boolean valid = (a > 0 && b <= 0) || (a <= 0 && b > 0);

but it can easly achieve with ^ XOR:

boolean valid = a > 0 ^ b > 0;

Now, in Kotline we don't use ^ as a XOR but just xor and same code in Kotlin looks like that:

val valid = a > 0 xor b > 0;

And here comes a problem because this code in Kotline gives ... compilation error!! Why? Because in Java all logical operator (&,&&,|,||,^) got lower precedence than relational operators (>, >=, <, <=, ==, !=). Same in Koltin but it looks like not for xor. So it goes this way:

  1. a > 0 gives boolean value
  2. boolean xor b > 0 first evealuated to: boolean xor b not b > 0
  3. And finally we got compilation error that said: The integer literal does not conform to the expected type Boolean

You can check this situation here: XOR not working well

One extra case: if you think that this one: a > 0 xor (b > 0) works... well, no. Another compilation error: Type mismatch: inferred type is Boolean but Int was expected

Can anyone explain me is there some purpouse for such logic or it's just a bug in Kotlin language?


Solution

  • xor is not an operator, but an infix function. Infix function calls have higher precedence than the comparison. Expressions

    val valid = a > 0 xor b > 0 is the same as val valid = a > (0 xor b) > 0

    1. (0 xor b) gives Int value
    2. a > (0 xor b) gives Boolean value
    3. and it turns into a comparison between Boolean and Int ((step 2 Boolean result) > 0), but you cannot compare Boolean with Int

    Correct version:

    val valid = (a > 0) xor (b > 0)