[Python-ideas] Null coalescing operators
abarnert at yahoo.com
Sun Sep 20 11:28:53 CEST 2015
On Sep 20, 2015, at 00:31, Steven D'Aprano <steve at pearwood.info> wrote:
>> On Sun, Sep 20, 2015 at 09:10:32AM +0300, Serhiy Storchaka wrote:
>>> On 19.09.15 07:21, Guido van Rossum wrote:
>>> I do, but at least the '?' is part of an operator, not part of the name
>>> (as it is in Ruby?).
>> What to do with the "in" operator?
> Absolutely nothing.
> I'm not convinced that we should generalise this beyond the three
> original examples of attribute access, item lookup and function call. I
> think that applying ? to arbitrary operators is a case of "YAGNI". Or
> perhaps, "You Shouldn't Need It".
I agree. Seeing how far you can generalize something and whether you can come up with a simple rule that makes all of your use cases follow naturally can be fun, but it isn't necessarily the best design.
Also, by not trying to generalize uptalk-combined operators (or uptalk as a postfix unary operator of its own, which I was earlier arguing for...), the question of how we deal with ?? or ?= (if we want them) can be "the same way every other language does", rather than seeing what follows from the general rule and then convincing ourselves that's what we wanted.
Also, I think trying to generalize to all operators is a false generalization, since the things we're generalizing from aren't actually operators (and not just syntactically--e.g., stylistically, they're never surrounded by spaces--which makes a pretty big difference in the readability impact of a character as heavy as "?") in the first place.
Personally, I think ?? is the second most obviously useful after ?. (there's a reason it's the one with the oldest and widest pedigree); we need ?() because Python, unlike C# and friends, unifies member and method access; ? doesn't seem as necessary but it's such an obvious parallel to ?() that I think people will expect it; ?= is potentially as confusing as it is helpful. So, my suggestion would be just the first four. And keeping them simple, and consistent with other languages, no trying to extend the protection to other operators/accesses, no extra short-circuiting, nothing. So:
spam ?? eggs === spam if spam is not None else eggs
spam?.eggs === spam.eggs if spam is not None else None
spam?(eggs) === spam(eggs) if spam is not None else None
spam?[eggs] === spam[eggs] if spam is not None else None
That's easy to define, easy to learn and remember, and pretty consistent with other languages. The one big difference is that what you write as "spam?.eggs(cheese)" in C# has to be "spam?.eggs?(cheese)" in Python, but I don't think that's a big problem. After all, in Python, spam.eggs is a first-class object, and one that's commonly passed or stored, so the obvious way to look at "spam.eggs(cheese)" is as explicitly chaining two separate things together (a __getattr__ with a descriptor __get__, and a __call__), so why shouldn't uptalking both operations be explicit?
More information about the Python-ideas