On 23 September 2015 at 19:21, Andrew Barnert
On Sep 23, 2015, at 02:00, Nick Coghlan
wrote: This may just be my C programmer brain talking, but reading the examples in PEP 505 makes me think of the existing use of "|" as the bitwise-or operator in both Python and C, and "||" as the logical-or operator in C.
The connection with || as a falsey-coalescing operator in C--and C#, Swift, etc., which have a separate null-coalescing operator that's spelled ??--seems like it could be misleading. Otherwise, I like it, but that's a pretty big otherwise.
One of the problems I occasionally see with folks migrating to Python from other languages is with our relatively expansive definition of "false" values. In particular, C/C++ developers expect all strings and containers (i.e. non-NULL pointers) to be truthy, with only primitive types (i.e. pointers and numbers) able to be false in a boolean content. Accordingly, the difference between C's || and a null-coalescing || in Python would be adequately covered by "Python has no primitive types, everything's an object or a reference to an object, so || in Python is like || with pointers in C/C++, where a reference to None is Python's closest equivalent to NULL". For example, a C/C++ dev might be tempted to write code like this: def example(env=None): env = env || {} ... With || as a null coalescing operator, that code's actually correct, while the same code with "or" would be incorrect: def example(env=None): env = env or {} # Also replaces a passed in empty dict ...
One additional wrinkle is that a single "|" would conflict with the bitwise-or notation in the case of None-aware index access, so the proposal for both that and attribute access would be to make the notation "!|", borrowing the logical negation "!" from "!=".
Maybe you should have given the examples first, because written on its own like this it looks unspeakably ugly, but in context below it's a lot nicer...
title!|.upper() person!|['name']
This actually makes me think of the ! from Swift and other languages ("I know this optionally-null object is not null even if the type checker can't prove it, so let me use it that way"), more than negation. Which makes the whole thing make sense, but in a maybe-unpythonically out-of-order way: the bang-or means "either title is not None so I get title.upper(), or it is so I get None".
It could also just be a "!" on its own, as the pipe isn't really adding much here: title!.upper() person!['name'] Then the "!" is saying "I know this may not exist, if it doesn't just bail out of this whole subexpression and produce None". That said, it's mainly the doubled "??" operator that I'm not fond of, I'm more OK with the "gracefully tolerate this being None" aspect of the proposal: title?.upper() person?['name']
I'm not sure whether other people will read it that way--or, if they do, whether it will be helpful or harmful mnemonically.
If this particular syntax were to be chosen, I also came up with the following possible mnemonics that may be useful as an explanatory tool:
"||" is a barrier to prevent None passing through an expression "!|" explicitly allows None to pass without error
That's definitely easy to understand and remember. But since Python doesn't exist in isolation, and null coalescing and null conditional operators exist in other languages and are being added to many new ones, it might be useful to use similar terms to other languages. (See https://msdn.microsoft.com/en-us/library/ms173224.aspx and https://msdn.microsoft.com/en-us/library/dn986595.aspx for how C# describes them.)
Those mnemonics are the "How would I try to explain this to a 10 year old?" version, rather than the "How would I try to explain this to a computer science student?" version. Assuming a null coalescing operator is added, I'd expect to see more formal language than that used in the language reference, regardless of the spelling chosen. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia