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

Andrew Barnert abarnert at yahoo.com
Sun Oct 4 00:59:06 CEST 2015


On Oct 3, 2015, at 13:27, Ron Adam <ron3200 at gmail.com> wrote:
> 
> On 10/02/2015 02:56 PM, Andrew Barnert via Python-ideas wrote:
>>> It's not quite the same.  The proposed ?( skips the arguments if
>>> the right hand side is None.
>>>> 
>>>> None?(...)   ---> None
>>>> 
>>>> So you can't use that to supply a default directly.
>>>> 
>>>> value = None?(default)    # returns None (not useful here)
>> Again, why would you want that to return default?
> 
> I guess it depends on what you think it should do.  None is a type, NoneType to be exact, then if like int, or float, what kind of argument should it have?

None isn't a type. None _has_ a type, just like 42 does. And, given that, it does exactly what I'd expect:

    >>> 42()
    TypeError: 'int' object is not callable
    >>> None()
    TypeError: 'NoneType' object is not callable
    >>> type(42)()
    0
    >>> type(None)()
    None
    >>> 42('23')
    TypeError: 'int' object is not callable
    >>> None('23')
    TypeError: 'NoneType' object is not callable
    >>> type(42)('23')
    23
    >>> type(None)('23')
    TypeError: NoneType takes no arguments

Calling int('23') makes sense as a conversion constructor; calling NoneType('23') doesn't.

But, even if you insisted that it should mean something, it would make far more sense for it to return None than '23'. After all, it's a constructor, it ought to construct an object of its type. But that still wouldn't mean that None should be callable just because NoneType is, any more than it means that 42 should be callable just because int is.

Meanwhile, you still haven't answered what "return the arguments" should actually mean, given that in Python, "the arguments" are a tuple of positional arguments plus a dict of keyword arguments. What would be the point in returning that? In a language where a 1-tuple is the same thing as its element, like the ML family or Haskell, and where there are no keyword arguments, something like this might be sensible. But in Python, it's not. Unless you have a way to make sense of it that I haven't thought of--which is why I'm asking.

> '' and empty containers come to mind.  Just like float and int can take '1', and error if you give it something that can't be converted to a float or int.
> 
> The None?(...) syntax looks like it should do a call.  Just like it would do if you did int?(...).

Again, int is a type, and None isn't. Callability is a special property that only certain types--functions, methods, types, and things that want to act like one of the above--have. None is not a function, method, or type, any more than 42 is.

Second, the whole reason spam?(…) has been proposed in the first place is that None(…) obviously doesn't make sense, so we want a way to avoid evaluating it if spam is None. In a language where everything is callable, there's no reason to even talk about ?().

> So both the return None and the return everything are special behaviors.  Possibly a None result is a bit more correct.

Making it return None isn't more correct, at least not for Python. It's definitely more correct for a language like SmallTalk with an "active null", which should propagate through almost all expressions by making them evaluate to None rather than raising. In such a language, for None(…) to do anything but return None would be inconsistent. But in a language where None doesn't propagate through any expressions, and instead usually raises a TypeError, for None(…) to return None would be highly inconsistent.

And if you're suggesting that we should replace None with a SmallTalk-style active null, that s a much bigger change, which would have to change a lot more than NoneType.__call__, in a way that would radically affect the semantics of millions of APIs, lines of code, etc.

> To tell the truth I think looking at some real examples from the library would be good.  How can those be improved both in how they read and how they look, and how frequent are they?

People have given real examples (from their own code, not the stdlib) for ?() as defined in the proposal. If you want examples for your different proposal, I think you're the one who needs to give them. (And I agree they would be worthwhile.)

> This whole line of discussion started out as a very tenuous suggestion/possibility.  I even said it was going out on a limb, so I really wasn't expecting to defend it as if it was a complete idea.
> 
> The concept I am thing of is doable, but not in the way I was thinking at first, but I also think it doesn't fit with python very well.

I think either it isn't doable, or it fits into Python even more poorly than you think. But I'm just one guy, who could easily be wrong. If you think otherwise, I would be interested in seeing what you can come up with. Even if it ends up not being a proposal you'd want to back, it would probably give insights to half the people involved in the larger discussion on null coalescing and null conditionals. And if it turns out that I'm right and you can't make it work, convincing yourself of that might lead to useful insights into the larger discussion that you could share here. After all, it seems like we're kind of stuck on conflicting incomplete intuitions here, and just arguing those back and forth isn't getting us very far.


More information about the Python-ideas mailing list