[Python-ideas] PEP 505 (None coalescing operators) thoughts

Steven D'Aprano steve at pearwood.info
Fri Oct 2 04:57:12 CEST 2015


On Thu, Oct 01, 2015 at 03:57:18PM -0500, Ron Adam wrote:
> On 10/01/2015 02:59 AM, Nick Coghlan wrote:
> 
> >As a result, one interesting way of looking at this problem is to
> >ask: what if we *only* offered the conditional operations, *without*
> >offering a binary null-coalescing operator?
> 
> How languages treat None, null, and nil, are very fundamental aspects of 
> how they work.  For example I noticed that if we add an None specific 
> 'or' operator, we may want a None specific 'and' operator too.

Why would we do that? What would it do and which other languages have 
it?


> And in order to use those in conditional statements, it makes sense to 
> have None specific 'if' and 'while'.

Which other languages have these?


> So it may be a slippery slope.  (Or 
> they may be good to have.  I'm very undecided still.)

Most slippery-slope arguments aren't actually that slippery. Sure, we 
could invent a new short-cut for "if spam is None" statement, but it 
doesn't buy us much benefit, so why would we bother?

    if spam.eggs[cheese] is None: ...
    ifn spam.eggs[cheese]: ...

You save a few characters typing, big deal. But with an expression, you 
can save complexity, by avoiding temporary variables:

    # before
    expensive = spam.eggs[cheese]  # don't calculate this twice
    value = expensive.attribute if expensive is not None else None

    # after
    value = spam.eggs[cheese]?.attribute



[...] 
> Another possibility is to have a *special magic callable* that when 
> called skips the argument evaluation and returns None.
> 
>     NoneCall(these, args, are, never, evaluated)

That cannot work with standard Python semantics. In Python, the function 
doesn't evaluate the arguments, they are evaluated before the function 
even gets called.

For this to work, the parser would have to recognise this NoneCall 
function *at compile time*, so it can decide whether or not to evaluate 
the arguments. That is, in general, an impossible task:

func = random.choice([NoneCall, lambda *args: None])
func(a+1, b*2, c**3)  # to evaluate or not to evaluate?


Python has only one thing even remotely like this, the special handling 
of "super" inside functions, and that's a special case which I think 
Guido has ruled won't be repeated. But even there, it isn't a change in 
what gets evaluated when.


> Then a special method on objects, obj __cond__call__() can return a 
> NoneCall to skip the arguments on the right side of ?(, or return 
> another callable to use them.

No, it can't work anything like that. It can't be a regular method call, 
because the arguments are already evaluated before the method call is 
made. It has to be a change in what code gets compiled.


-- 
Steve


More information about the Python-ideas mailing list