On Mon, Sep 21, 2015 at 2:23 PM, Terry Reedy email@example.com wrote:
Add me to the detractors of what I have read so far ;-).
In arithmetic, 1/0 and 0/0 both stop the calculation. My hand calculator literally freezes until I hit 'on' or 'all clear'. Early computers also stopped, maybe with an instruction address and core dump. Three orthogonal solutions are: test y before x/y, so one can do something else; introduce catchable exceptions, so one can do something else; introduce contagious special objects ('inf' and 'nan'), which at some point can be tested for, so one can do something else. Python introduced 'inf' and 'nan' but did not use them to replace ZeroDivisionError.
Some languages lacking exceptions introduce a contagious null object. Call it Bottom. Any operation on Bottom yields Bottom. Python is not such a language. None is anti-contagious; most operations raise an exception.
I agree with Paul Moore that propagating None is generally a bad idea. It merely avoids the inevitable exception. Or is it inevitable? Trying to avoid exceptions naturally leads to the hypergeneralization of allowing '?' everywhere.
Instead of trying to turn None into Bottom, I think a better solution would be a new, contagious, singleton Bottom object with every possible special method, all returning Bottom. Anyone could write such for their one use. Someone could put it on pypi to see if there how useful it would be.
I think this is the PyMaybe solution. What I don't like about it is that it is dynamic -- when used incorrectly (or even correctly?) Bottom could end up being passed into code that doesn't expect it. That's bad -- "if x is None" returns False when x is Bottom, so code that isn't prepared for Bottom may well misbehave. In contrast, PEP 505 only affects code that is lexically near the ? operator.
(You may see a trend here. PEP 498 is also carefully designed to be locally-scoped.)
I agree with Ron Adam that the narrow issue is that bool(x) is False is sometimes too broad and people dislike of spelling out 'x is not None'. So abbreviate that with a unary operator; 'is not None', is a property of objects, not operators. I think 'x!' or 'x?', either meaning 'x is not None', might be better than a new binary operator. The former, x!, re-uses ! in something close to its normal meaning: x really exists.
I don't think the big issue is bool(x) being too broad. That's what the binary ?? operator is trying to fix, but to me the more useful operators are x?.y and x?[y], both of which would still require repetition of the part on the left when spelled using ??.
This is important when x is a more complex expression that is either expensive or has a side-effect. E.g. d.get(key)?.upper() would currently have to be spelled as (some variant of) "None if d.get(key) is None else d.get(key).upper()" and the ?? operator doesn't really help for the repetition -- it would still be "d.get(key) ?? d.get(key).upper()".
In general to avoid this repetition you have to introduce a local variable, but that's often awkward and interrupts the programmer's "flow". The ? solves that nicely. The key issue with this proposal to me is how it affects readability of code that uses it, given that there isn't much uniformity across languages in what ? means -- it could be part of a method name indicating a Boolean return value (Ruby) or a conditional operator (C and most of its descendents) or some kind of shortcut.
So this is the issue I have to deal with (and thought I had dealt with by prematurely rejecting the PEP, but I've had a change of heart and am now waiting for the PEP to be finished).