Discussion about a 'xor' keyword?

You've probably read this title with skepticism. I know I would. As the title says. I am curious as to engage in the discussion, and see what everyone's thoughts are on it. I know this has been discussed in the past several years ago ( https://mail.python.org/pipermail/python-3000/2007-December/011560.html ) and on various websites already. I've found myself writing code that would be simpler with a xor keyword or similar syntax, and this is why I'm suggesting this. Here are my thoughts: Since 'a or b' and 'a and b' return either a or b, what should 'a xor b' return? I have a few ideas, and no particular preference: To be consistent with other binary operators, 'xor' should return one of its operands, IMO. So 'a xor b' should be a if a is True and b is False, and b if b is True and a is False. That much makes sense so far (to me). What I'm a bit less sure about is what to return in the case that both are True, or both False. We already have a per-type definition of xor, and if we want to have only the boolean xor, we can easily do 'bool(a) ^ bool(b)' and so I feel this discussion should disregard the possibility of returning only a boolean value; we can already do that in a way that a keyword wouldn't help. My thoughts on this would be to return either a or b if only one of them is True in a boolean context, else return None. None is a fairly common name already, and we could use it to say that the exclusive-or check returned no value (just like a function call). I don't think adding a new builtin name would be the way to go - adding a new keyword is already a big breaking change. If one of the two values is None already... well then I guess that's something to be fixed in the code? That's one of the things that should probably be discussed, should the people on this list be favorable to the idea. I'm expecting there'll be some sort of BDFL pronouncement at some point, but I still want to have the discussion. If it gets rejected, I would at least be happy if some discussion took place to talk about it. -Emanuel Barry

On 18.10.15 01:17, Emanuel Barry wrote:
'and' and 'or' are short-circuit operators. But 'xor' needs to know values of both operands. Therefore no need in the xor operator, it can be a function. def xor(a, b): if a: if b: return None else: return a else: if b: return b else: return None But I suppose that in most cases boolean result is enough, and it can be written as bool(a) != bool(b).

On 17/10/2015 23:50, Emile van Sebille wrote:
The only one I can find that refers specifically to xor is PEP 225 -- Elementwise/Objectwise Operators[1]. Which others have I missed? [1] https://www.python.org/dev/peps/pep-0225/
-- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence

On Sat, Oct 17, 2015 at 3:17 PM, Emanuel Barry <vgr255@live.ca> wrote:
There were a couple times in the past when I found myself wanting a "xor" operator for clarity/aesthetics. In the most recent case, it was to express a validity condition for rows in an SQL DB table which was acting like a tagged union, so only 1 of a subset of the columns in a given row could be non-NULL. That case would have been served just fine by a simple version of xor that always gave a bool result. However, it ultimately turned out that what I really wanted was an "exactly 1 of these N subconditions must be true" operation, which doesn't correspond to conventional definitions of XOR (they instead calculate a parity bit; see http://mathworld.wolfram.com/XOR.html ). So xor would only truly have been useful in cases when N just-so-happens to be 2, and therefore I no longer hunger for a "xor" keyword. I would be interested to hear what your concrete use cases for xor are. Cheers, Chris -- http://chrisrebert.com

On Sat, Oct 17, 2015 at 3:17 PM, Emanuel Barry <vgr255@live.ca> wrote:
This 2009 discussion was more vigorous: https://mail.python.org/pipermail/python-list/2009-July/543956.html Cheers, Chris

Having a look right now. Looks interesting.
I would be interested to hear what your concrete use cases for xor are.
I have a few from the top of my head (not backed by code right now, will post some when I feel like digging into it). For an IRC game bot I work on, we have a special message if someone has two targets available, but a different one if they have only one - although it's the same message, and we made a complicated conditional just for that. A xor keyword would have saved us that trouble. In a library I dug in some time ago (I didn't make it), an exception was raised if two parameters had a True (or False) value - one of them had to be True. I (probably naively) think that some more libraries do that. My friend in college is learning programming, and for his projects he says he really wants to see a 'xor' keyword in, as he has to do some mangling to get what he wants. I'm unaware what his work consists of, however. ------------------ 'xor' would by no means be as common as any existing operator, but I believe it is a good addition to consider. Another upside is that keywords only evaluate the value once, so chaining two wouldn't re-evaluate the value (in the case of a function/property).

First, it seems like if this operator were to exist, it should be defined in terms of "and", "or", and "not" in one of the usual ways: "a and not b or b and not a", or "(a or b) and not (a and b)". Of course this means it returns False, not None, if both values are falsey or both truthy, but I think that's what you'd want anyway. While you sometimes do want the value of "a and b" or "a or b", it's far more common to just want the truthiness of that value (as in "if a or b:"), and, while None is falsey, it's not the canonical falsey value. But anyway, as my replies below explain, I don't think it should exist. On Saturday, October 17, 2015 6:54 PM, Emanuel Barry <vgr255@live.ca> wrote:
I have a few from the top of my head (not backed by code right now, will post some when I feel like digging into it).
But all of these ideas are just as well served by a function as by a new keyword. There are two reasons for "and" and "or" to be operators. First, functions can't short-circuit. That's obviously not relevant to "xor", because by definition, it has to evaluate both operands. Second, function calls chained in a complicated expression can look ugly compared to operators—compare "or(and(a, b), and(c, d))" to "a and b or c and d". But that isn't relevant to "xor" either. I think most readers would find "a xor b xor c xor d xor e" confusing and have to work through its meaning—and, in fact, they'd find xor(a, xor(b, xor(c, xor(d, e))))" (or the reverse associativity) easier to understand. Worse, I think some readers would _think_ they understand what it means and be wrong (exactly one, or some but not all, or exactly half). And, more importantly, I don't think they'd ever want what it does. It's pretty common to want to check that one or all of three values are true, but when would you ever want to check that an odd number of those three values are true? (You might occasionally want to check that an odd number of the possibly-only-known-at-runtime members of some iterable are true, but for that, you'd use a function akin to "any" and "all", maybe called "parity".)
'xor' would by no means be as common as any existing operator, but I believe it is a good addition to consider. Another upside is that keywords only evaluate the value once, so chaining two wouldn't re-evaluate the value (in the case of a function/property).
Again, I don't think you'd want to chain them. But, even if you did, functions also only evaluate their arguments once, so there's no advantage here anyway. For example, try this: def xor(a, b): return a and not b or b and not a xor((print('spam'), 2)[1], (print('eggs'), 3)[1]) Of course "spam" and "eggs" only get printed once, because what gets passed to "xor" isn't the expression "(print('spam'), 2)[1]", it's the value of that expression, "2". And likewise, xor(a, xor(b, c)) isn't going to cause b or c to get evaluated twice. And of course neither would "parity((a, b, c))" or "some((a, b, c))", etc. And I'm not sure what you mean by "property" here.
From that 2009 discussion, most of the rejections focused on "You can coerce to bool before then perform the xor operations", but I'm considering not coercing to bool here, so I think it is different enough to the other discussion to (at least in my opinion) bring it up one more time. If I wanted boolean coercion, I'd just do it myself.
But you can also just do it yourself _without_ boolean coercion, so how is this any different?

This just isn't going to happen. The combination of the expense of a new keyword, the lack of use cases that can't be done just as easily with a function, and the murky definition make it a non-started. -- --Guido van Rossum (python.org/~guido)

I figured as much, thanks anyway. Cheers,-Emanuel Barry From: guido@python.org Date: Sun, 18 Oct 2015 08:00:51 -0700 Subject: Re: [Python-ideas] Discussion about a 'xor' keyword? To: abarnert@yahoo.com CC: vgr255@live.ca; python-ideas@python.org This just isn't going to happen. The combination of the expense of a new keyword, the lack of use cases that can't be done just as easily with a function, and the murky definition make it a non-started. -- --Guido van Rossum (python.org/~guido)

On 18.10.15 01:17, Emanuel Barry wrote:
'and' and 'or' are short-circuit operators. But 'xor' needs to know values of both operands. Therefore no need in the xor operator, it can be a function. def xor(a, b): if a: if b: return None else: return a else: if b: return b else: return None But I suppose that in most cases boolean result is enough, and it can be written as bool(a) != bool(b).

On 17/10/2015 23:50, Emile van Sebille wrote:
The only one I can find that refers specifically to xor is PEP 225 -- Elementwise/Objectwise Operators[1]. Which others have I missed? [1] https://www.python.org/dev/peps/pep-0225/
-- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence

On Sat, Oct 17, 2015 at 3:17 PM, Emanuel Barry <vgr255@live.ca> wrote:
There were a couple times in the past when I found myself wanting a "xor" operator for clarity/aesthetics. In the most recent case, it was to express a validity condition for rows in an SQL DB table which was acting like a tagged union, so only 1 of a subset of the columns in a given row could be non-NULL. That case would have been served just fine by a simple version of xor that always gave a bool result. However, it ultimately turned out that what I really wanted was an "exactly 1 of these N subconditions must be true" operation, which doesn't correspond to conventional definitions of XOR (they instead calculate a parity bit; see http://mathworld.wolfram.com/XOR.html ). So xor would only truly have been useful in cases when N just-so-happens to be 2, and therefore I no longer hunger for a "xor" keyword. I would be interested to hear what your concrete use cases for xor are. Cheers, Chris -- http://chrisrebert.com

On Sat, Oct 17, 2015 at 3:17 PM, Emanuel Barry <vgr255@live.ca> wrote:
This 2009 discussion was more vigorous: https://mail.python.org/pipermail/python-list/2009-July/543956.html Cheers, Chris

Having a look right now. Looks interesting.
I would be interested to hear what your concrete use cases for xor are.
I have a few from the top of my head (not backed by code right now, will post some when I feel like digging into it). For an IRC game bot I work on, we have a special message if someone has two targets available, but a different one if they have only one - although it's the same message, and we made a complicated conditional just for that. A xor keyword would have saved us that trouble. In a library I dug in some time ago (I didn't make it), an exception was raised if two parameters had a True (or False) value - one of them had to be True. I (probably naively) think that some more libraries do that. My friend in college is learning programming, and for his projects he says he really wants to see a 'xor' keyword in, as he has to do some mangling to get what he wants. I'm unaware what his work consists of, however. ------------------ 'xor' would by no means be as common as any existing operator, but I believe it is a good addition to consider. Another upside is that keywords only evaluate the value once, so chaining two wouldn't re-evaluate the value (in the case of a function/property).

First, it seems like if this operator were to exist, it should be defined in terms of "and", "or", and "not" in one of the usual ways: "a and not b or b and not a", or "(a or b) and not (a and b)". Of course this means it returns False, not None, if both values are falsey or both truthy, but I think that's what you'd want anyway. While you sometimes do want the value of "a and b" or "a or b", it's far more common to just want the truthiness of that value (as in "if a or b:"), and, while None is falsey, it's not the canonical falsey value. But anyway, as my replies below explain, I don't think it should exist. On Saturday, October 17, 2015 6:54 PM, Emanuel Barry <vgr255@live.ca> wrote:
I have a few from the top of my head (not backed by code right now, will post some when I feel like digging into it).
But all of these ideas are just as well served by a function as by a new keyword. There are two reasons for "and" and "or" to be operators. First, functions can't short-circuit. That's obviously not relevant to "xor", because by definition, it has to evaluate both operands. Second, function calls chained in a complicated expression can look ugly compared to operators—compare "or(and(a, b), and(c, d))" to "a and b or c and d". But that isn't relevant to "xor" either. I think most readers would find "a xor b xor c xor d xor e" confusing and have to work through its meaning—and, in fact, they'd find xor(a, xor(b, xor(c, xor(d, e))))" (or the reverse associativity) easier to understand. Worse, I think some readers would _think_ they understand what it means and be wrong (exactly one, or some but not all, or exactly half). And, more importantly, I don't think they'd ever want what it does. It's pretty common to want to check that one or all of three values are true, but when would you ever want to check that an odd number of those three values are true? (You might occasionally want to check that an odd number of the possibly-only-known-at-runtime members of some iterable are true, but for that, you'd use a function akin to "any" and "all", maybe called "parity".)
'xor' would by no means be as common as any existing operator, but I believe it is a good addition to consider. Another upside is that keywords only evaluate the value once, so chaining two wouldn't re-evaluate the value (in the case of a function/property).
Again, I don't think you'd want to chain them. But, even if you did, functions also only evaluate their arguments once, so there's no advantage here anyway. For example, try this: def xor(a, b): return a and not b or b and not a xor((print('spam'), 2)[1], (print('eggs'), 3)[1]) Of course "spam" and "eggs" only get printed once, because what gets passed to "xor" isn't the expression "(print('spam'), 2)[1]", it's the value of that expression, "2". And likewise, xor(a, xor(b, c)) isn't going to cause b or c to get evaluated twice. And of course neither would "parity((a, b, c))" or "some((a, b, c))", etc. And I'm not sure what you mean by "property" here.
From that 2009 discussion, most of the rejections focused on "You can coerce to bool before then perform the xor operations", but I'm considering not coercing to bool here, so I think it is different enough to the other discussion to (at least in my opinion) bring it up one more time. If I wanted boolean coercion, I'd just do it myself.
But you can also just do it yourself _without_ boolean coercion, so how is this any different?

This just isn't going to happen. The combination of the expense of a new keyword, the lack of use cases that can't be done just as easily with a function, and the murky definition make it a non-started. -- --Guido van Rossum (python.org/~guido)

I figured as much, thanks anyway. Cheers,-Emanuel Barry From: guido@python.org Date: Sun, 18 Oct 2015 08:00:51 -0700 Subject: Re: [Python-ideas] Discussion about a 'xor' keyword? To: abarnert@yahoo.com CC: vgr255@live.ca; python-ideas@python.org This just isn't going to happen. The combination of the expense of a new keyword, the lack of use cases that can't be done just as easily with a function, and the murky definition make it a non-started. -- --Guido van Rossum (python.org/~guido)
participants (7)
-
Andrew Barnert
-
Chris Rebert
-
Emanuel Barry
-
Emile van Sebille
-
Guido van Rossum
-
Mark Lawrence
-
Serhiy Storchaka