[Python-ideas] PEP 505 [was Re: Null coalescing operators]

Steven D'Aprano steve at pearwood.info
Wed Sep 23 18:47:00 CEST 2015


I've now read PEP 505, and I would like to comment.

Executive summary:

- I have very little interest in the ?? and ?= operators, but don't 
  object to them: vote +0

- I have a little more interest in ?. and ?[ provided that the
  precedence allows coalescing multiple look-ups from a single
  question mark: vote +1

- if it uses the (apparent?) Dart semantics, I am opposed: vote -1

- if the syntax chosen uses || or !| as per Nick's suggestion, 
  I feel the cryptic and ugly syntax is worse than the benefit: 
  vote -1


In more detail:

I'm sympathetic to the idea of reducing typing, but I think it is 
critical to recognise that reducing typing is not always a good thing. 
If it were, we would always name our variables "a", "b" etc, the type of 
[] would be "ls", and we would say "frm col impt ODt". And if you have 
no idea what that last one means, that's exactly my point.

Reducing typing is a good thing *up to a point*, at which time it 
becomes excessively terse and cryptic. One of the things I like about 
Python is that it is not Perl: it doesn't have an excess of punctuation 
and short-cuts. Too much syntactic sugar is a bad thing. 

The PEP suggests a handful of new operators:

(1) Null Coalescing Operator

    spam ?? eggs

equivalent to a short-circuiting:

    spam if spam is not None else eggs

I'm ambivalent about this. I don't object to it, but nor does it excite 
me in the least. I don't think the abbreviated syntax gains us enough in 
expressiveness to make up for the increase in terseness. In its favour, 
it can reduce code duplication, and also act as a more correct 
alternative to `spam or eggs`. (See the PEP for details.)

So I'm a very luke-warm +0 on this part of the PEP.



(2) None coalescing assignment

    spam ?= eggs

being equivalent to:

    if spam is None:
        spam = eggs

For the same reasons as above, I'm luke-warm on this: +0.



(3) Null-Aware Member Access Operator

    spam?.attr

being equivalent to

    spam.attr if spam is not None else None

To me, this passes the test "does it add more than it costs in cryptic 
punctuation?", so I'm a little more positive about this.

If my reading is correct, the PEP underspecifies the behaviour of this 
when there is a chain of attribute accesses. Consider:

    spam?.eggs.cheese

This can be interpreted two ways:

    (a)  (spam.eggs.cheese) if spam is not None else None

    (b)  (spam.eggs if spam is not None).cheese

but the PEP doesn't make it clear which behaviour they have in mind. 
Dart appears to interpret it as (b), as the reference given in the 
PEP shows this example:

    [quote]
    You can chain ?. calls, for example:
    obj?.child?.child?.getter
    [quote]

http://blog.sethladd.com/2015/07/null-aware-operators-in-dart.html

That would seem to imply that obj?.child.child.getter would end up 
trying to evaluate null.child if the first ?. operator returned null.

I don't think the Dart semantics is useful, indeed it is actively 
harmful in that it can hide bugs:

Suppose we have an object which may be None, but if not, it must 
have an attribute spam which in turn must have an attribute eggs. This 
implies that spam must not be None. We want:

    obj.spam.eggs if obj is not None else None

Using the Dart semantics, we chain ?. operators and get this:

    obj?.spam?.eggs

If obj is None, the expression correctly returns None. If obj is not 
None, and obj.spam is not None, the expression correctly returns eggs. 
But it is over-eager, and hides a bug: if obj.spam is None, you want to 
get an AttributeError, but instead the error is silenced and you get 
None.

So I'm -1 with the Dart semantics, and +1 otherwise.



(3) Null-Aware Index Access Operator

    spam?[item]

being similar to spam.attr. Same reasoning applies to this as for 
attribute access.



Nick has suggested using || instead of ??, and similar for the other 
operators. I don't think this is attractive at all, but the deciding 
factor which makes Nick's syntax a -1 for me is that it is inconsistent 
and confusing. He has to introduce a !| variation, so the user has to 
remember when to use two |s and when to use a ! instead, whether the ! 
goes before or after the | and that !! is never used.



-- 
Steve


More information about the Python-ideas mailing list