• Subject: Re: Why don't bools have (some) bitwise operators?
• From: Philippe Verdy <verdyp@...>
• Date: Wed, 24 Feb 2021 16:12:42 +0100

Also remember that with boolean-only algebra:

a xor b
===  (a and not b)   or         (b and not a)
===  not(a or b)     and  not (not a or not b)

So the xor can be both canonicalized as an or-list of and-list of single boolean tests, or an and-list of or-list of single-boolean tests ("tests" being evaluating if they are false or true, with an "identity" or "complementary not" function); that's why "xor" should have higher priority than "or"/"and", but not placed in the middle of them (because "or"/"and" implement shortcuts on the evaluation of their operands, which "xor" would not as it would behave like other binary operators like "+", "*", "==", "~=", ">", and so on).

Le mer. 24 févr. 2021 à 16:01, Philippe Verdy <verdyp@gmail.com> a écrit :

Le mer. 24 févr. 2021 à 04:08, Sudipto Mallick <smallick.dev@gmail.com> a écrit :
On Wed, Feb 24, 2021, 5:19 AM Sean Conner <sean@conman.org> wrote:
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)

-spc

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:

not a() ~= not b()

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

would mean:

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).