[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