Also, "and" and "or" in Lua short-circut evaluation.
if foo() and bar() then ... end
if foo() returns false, bar() is not called (because the rest of the
_expression_ can never be true)
if foo() or bar() then ... end
if foo() returns true, bar() is never called (because the _expression_ as a
whole is true)
Yes, that's understandable. Short-circuiting for `and` and `or` works because in Boolean algebra, we have:
1 or A = 1
0 and A = 0
for any Boolean value of A.
But, in case of `xor`, you need to evaluate both sides to get the result. For example, look at the way OP was doing `xor` from its textbook definition:
(A and not B) or (not A and B)
Short circuit or not: You need to evaluate both of A and B. If A=1 then the `not B` is evaluated. If A=0 then `(not A and B)` and subsequently `B` is evaluated.
There's still some short-circuit evaluating both results without needing a temporary variable:
a() ~= b()
Note however this should be consistant with Lua's booleans (as used with if/ifelse/while/and/or/no), you have to take care of return values other than false or true, notably nil, 0, NaN, all other numbers values (including infinite), strings, or object references (tables, functions, userdata...), so you may need to convert the values to boolean. The simplest way is to use "not" on both sides of the "~=" comparison:
which would be what Lua should do if it implements the "xor" operator for booleans (featuring conversion to booleans, like in if/ifelse/while/and/or/not) :
a() xor b()
such addition of keyword however would requiring defining a priority for the operator, which should be higher than the priority "and", itself having higher priority than "or", so that
a or b and c xor d
a or (b and (c xor d))
This "xor" boolean operator would implement no short-circuit (both operands being evaluated, the left one before the right one -- the order being important when operands contain function calls or access checks causing errors/exceptions, or "meta" function calls via remapped operators).