Steven, thanks for the reply. Just to clarify: the current PEP draft was not meant to be read -- it was just a placeholder to get a PEP # assigned. I didn't realize that new PEPs are published in an RSS feed!

I do appreciate your detailed feedback, though. Your interpretation of Dart's semantics is correct, and I agree that's absolutely the wrong way to do it. C# does have the short-circuit semantics that you're looking for.

To you, and to everybody else in this thread: I am reading every single message, and I'm working on a draft worthy of your time and attention that incorporates all of these viewpoints and offers several, competing alternatives. I will announce the draft on this list when I'm further along.

Proposing a new operator is tremendously difficult in Python, because this community doesn't like complex or ugly punctuation. (And adding a new keyword won't happen any time soon.) A similar debate surrounded the ternary operator PEP[1]. That PEP's author eventually held a vote on the competing alternatives, including an option for "don't do anything". I'm hoping to hold a similar referendum on this PEP once I've had time to work on it a bit more.


On Wed, Sep 23, 2015 at 12:47 PM, Steven D'Aprano <> wrote:
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


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:


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:

    You can chain ?. calls, for example:

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:


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

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

(3) Null-Aware Index Access Operator


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.

Python-ideas mailing list
Code of Conduct:

Mark E. Haase