On 19.09.2015 01:18, Erik wrote:Apologies for the self-reply. I just wanted to clarify a couple of
things.
On 18/09/15 23:56, Erik wrote:If the foo operator uses the magic method "__foo__" to mean "return an
object to be used in place of the operand should it be considered ...
false? [or some other definition - I'm not sure]"
Not "false", I think. The "foo" operator is meant to mean "I will go
on to use the resulting object in any way imaginable and it must cope
with that and return a value from any attempts to use it that will
generally mean 'no'" (*).If that was a postfix operator which has a high precedence, then:
bar = foo?
bar.isoformat()
and the original syntax suggestion:
bar = foo?.isoformat()
Which is clearly wrong - the first part should be:
baz = foo?
bar = baz.isoformat()
E.
(*) Should we call the operator "shrug"?
Maybe monad?
Python-ideas mailing list
Python...@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/
Andrew, I really like that idea. Turning back to the null coalescing operator (spelled ?? in other languages), how do you think that fits in?Consider this syntax:>>> None? or 1
This also doesn't work quite right. If both operands are None, we want the expression to evaluate to None, not NoneQuestion. Should null coalescing be a separate operator? And if so, are "?" and "??" too similar?
Can anybody think of realistic use cases for overriding a magic method for the "?" operator? I would like to include such use cases in a PEP. One possible use case: being able to coalesce empty strings.>>> s1 = MyString('')>>> s2 = MyString('foobar')>>> s1? or s2MyString('foobar')
It's a funny thing, I'm usually not a huge fan of symbols outside of
maths operators, and I strongly dislike the C ? ternary operator, but
this one feels really natural to me. I didn't have even the most
momentary "if you want Perl, you know where to find it" thought.
On Fri, Sep 18, 2015 at 8:41 PM, Steven D'Aprano <st...@pearwood.info> wrote:It's a funny thing, I'm usually not a huge fan of symbols outside of
maths operators, and I strongly dislike the C ? ternary operator, but
this one feels really natural to me. I didn't have even the most
momentary "if you want Perl, you know where to find it" thought.I do, but at least the '?' is part of an operator, not part of the name (as it is in Ruby?).I really, really, really don't like how it looks, but here's one thing: the discussion can be cut short and focus almost entirely on whether this is worth making Python uglier (and whether it's even ugly :-). The semantics are crystal clear and it's obvious that the way it should work is by making "?.", ?(" and "?[" new operators or operator pairs -- the "?" should not be a unary postfix operator but a symbol that combines with certain other symbols.
A true SQL NULL type. It's always bothered me that most ORMs map NULL to None but there are plenty of other ways to inject None into a Python computation. (This probably isn't a practical suggestion either unless Random832's suggestion of ?() establishing a lexical context were adopted.)
The point is that Maybe behavior is at least theoretically useful in subcategories, with special objects other than None. Sven's suggestion of calling this the "monad" operator triggers a worry in me, however. In Haskell, the Monad type doesn't enforce the monad laws, only the property of being an endofunctor. That apparently turns out to be enough in practice to make the Monad type very useful. However, in Python we have no way to enforce that property. I don't have the imagination to come up with a truly attractive nuisance here, and this operator doesn't enable general functorial behavior, so maybe it's not a problem.
On 19.09.2015 14:48, Stephen J. Turnbull wrote:Sven R. Kunze writes:Issue is, None is so convenient to work with. You only find out the
code smell when you discover a "NoneType object does not have
attribute X"
That's exactly what should happen (analogous to a "signalling NaN").
Not my point, Stephen. My point is, you better avoid None (despite its
convenience) because you are going to have a hard time finding its
origin later in the control flow.
Question still stands: is None really necessary to justify the
introduction of convenience operators like "?." etc.?The problem is if you are using None as a proxy for a NULL in another
subsystem that has "NULL contagion" (I prefer that to "coalescing").
How would you solve instead?
Best,
Sven
Python-ideas mailing list
Python...@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/
I think the core issue is that, whether or not it should be used, APIs already return None values, so a convenience operator might as well be added.
Xavier Combelle
<xavier....@gmail.com> writes:
> I'm curious on which API returning None, a major bonus on using python
> is that I pretty never stumbled upon the equivalent of
> NullPointerException.
It doesn't strictly have one; None is an object and you get the usual
TypeError, AttributeError, etc, upon using it in a place it's not expected.
a.b?(p, q).c.d[x, y] === None if a.b is None else a.b(p, q).c.d[x, y]a.b?[x, y].c.d(p, q) === None if a.b is None else a.b[x, y].c.d(p, q)I forgot to think about the scope of the uptalk operator (i.e. what is skipped when it finds a None). There are some clear cases (the actual implementation should avoid double evaluation of the tested expression, of course):a.b?.c.d[x, y](p, q) === None if a.b is None else a.b.c.d[x, y](p, q)
But what about its effect on other operators in the same expression? I think this is reasonable:a?.b + c.d === None if a is None else a.b + c.d
f(a?.b) === f((None if a is None else a.b))(a?.b, x) === ((None if a is None else a.b), x)It also shouldn't escape out of comma-separated lists, argument lists, etc.:
On Sat, Sep 19, 2015 at 03:17:07AM -0500, C Anthony Risinger wrote:
> I really liked this whole thread, and I largely still do -- I?think -- but
> I'm not sure I like how `?` suddenly prevents whole blocks of code from
> being evaluated. Anything within the (...) or [...] is now skipped (IIUC)
> just because a `?` was added, which seems like it could have side effects
> on the surrounding state, especially since I expect people will use it for
> squashing/silencing or as a convenient trick after the fact, possibly in
> code they did not originally write.
I don't think this is any different from other short-circuiting
operators, particularly `and` and the ternary `if` operator:
result = obj and obj.method(expression)
result = obj.method(expression) if obj else default
In both cases, `expression` is not evaluated if obj is falsey. That's
the whole point.
> If the original example included a `?` like so:
>
> response = json.dumps?({
> 'created': created?.isoformat(),
> 'updated': updated?.isoformat(),
> ...
> })
>
> should "dumps" be None, the additional `?` (although though you can barely
> see it) prevents *everything else* from executing.
We're still discussing the syntax and semantics of this, so I could be
wrong, but my understanding of this is that the *first* question mark
prevents the expressions in the parens from being executed:
json.dumps?( ... )
evaluates as None if json.dumps is None, otherwise it evaluates the
arguments and calls the dumps object. In other words, rather like this:
_temp = json.dumps # temporary value
if _temp is None:
response = None
else:
response = _temp({
'created': None if created is None else created.isoformat(),
'updated': None if updated is None else updated.isoformat(),
...
})
del _temp
except the _temp name isn't actually used. The whole point is to avoid
evaluating an expression (attribute looking, index/key lookup, function
call) which will fail if the object is None, and if you're not going to
call the function, why evaluate the arguments to the function?
> Usually when I want to use this pattern, I find I just need to write things
> out more. The concept itself vaguely reminds me of PHP's use of `@` for
> squashing errors.
I had to look up PHP's @ and I must say I'm rather horrified. According
to the docs, all it does is suppress the error reporting, it does
nothing to prevent or recover from errors. There's not really an
equivalent in Python, but I suppose this is the closest:
# similar to PHP's $result = @(expression);
try:
result = expression
except:
result = None
This is nothing like this proposal. It doesn't suppress arbitrary
errors. It's more like a conditional:
# result = obj?(expression)
if obj is None:
result = None
else:
result = obj(expression)
If `expression` raises an exception, it will still be raised, but only
if it is actually evaluated, just like anything else protected by an
if...else or short-circuit operator.
If I know, the value definitely needs to be IN the dictionary, I use dict[...].
PEP-505 isn't anywhere close to being finished. I only submitted the draft because somebody off list asked me to send a draft so I could get a PEP number assigned. So I literally sent him what I had open in my text editor, which was just a few minutes of brain dumping and had several mistakes (grammatical and technical).If there's absolutely no point in continuing to work on it, I'll drop it. But from the outset, I thought the plan was to present this in its best light (and similar to the ternary operator PEP, offer several alternatives) if for no other reason than to have a good record of the reasoning for rejecting it.I'm sorry if I misunderstood the PEP process; I would have kept it to myself longer if I knew the first submission was going to be reviewed critically. I thought this e-mail chain was more of an open discussion on the general idea, not specifically a referendum on the PEP itself.
On Mon, Sep 21, 2015 at 11:40 AM, Guido van Rossum <gu...@python.org> wrote:Just to cut this thread short, I'm going to reject PEP 505, because ? is just too ugly to add to Python IMO. Sorry.I commend Mark for his clean write-up, without being distracted, giving some good use cases. I also like that he focused on a minimal addition to the language and didn't get distracted by hyper-generalizations.
I also like that he left out f?(...) -- the use case is much weaker; usually it's the object whose method you're calling that might be None, as in title?.upper().Some nits for the PEP:- I don't think it ever gives the priority for the ?? operator. What would "a ?? b or c" mean?- You don't explain why it's x ?? y but x ?= y. I would have expected either x ? y or x ??= y.- You don't explain or show how far ?. reaches; I assume x?y.z is equivalent to None if x is None else x.y.z, so you don't have to write x?.y?.z just to handle x.y.z if x is None.- The specification section is empty.--
_______________________________________________
Python-ideas mailing list
Python...@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/
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 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.
On 9/21/2015 5:48 PM, Guido van Rossum wrote:
On Mon, Sep 21, 2015 at 2:23 PM, Terry Reedy
<tjr...@udel.edu
<mailto:tjr...@udel.edu>> wrote:
I agree with Paul Moore that propagating None is generally a bad
idea. It merely avoids the inevitable exception.
To me, this is the key idea in opposition to proposals that make propagating None easier.
I don't think the big issue is bool(x) being too broad. That's what the> "None if d.get(key) is None else d.get(key).upper()"
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)
> 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".
try:
x = d.get(key).upper()
except AttributeError:
x = None
is also a no-repeat equivalent when d.values are all strings. I agree than "x = d.get(key)?.upper()" is a plausible abbreviation. But I am much more likely to want "x = ''" or another exception as the alternative. I guess some other pythonistas like keeping None around more than I do ;-).
On Mon, Sep 21, 2015, at 17:48, Guido van Rossum wrote:
> 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()".
?? is meant to use the right if the left *is* null, as I understand it.
So this isn't a problem it solves at all.
My jaw dropped a bit when I saw it asserted in this thread that
functions returning "useful value or None" is an anti-pattern. I write
functions like that all the time, and I consider it a useful and
necessary Python idiom. I would hate to rewrite all that code to either
deal with exceptions or add default-value-argument boilerplate to all of
them; when "no result" is an expected and normal possibility from a
function, letting the calling code deal with None however it chooses is
much nicer than either of those options.
(1) it's strongly related to the . [] () syntax;(2) any syntax that uses a keyword is either not syntactically related to . [] () or mixes a keyword and punctuation, both of which I dislike;
(3) it's the same syntax as used in other languages (yes, Python is not C# or Dart but there's a good reason Python uses ^ for xor, ** for power, += for add to, etc.)
>
> 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).
>
As we are in the process of writing a PEP and uses of ?/?? in other languages,
why not speak about thecurrent usage of `?` / `??` in the Python community ?
(I'll try to state only facts, excuse any passage that might seem like
a personal opinion)
Can the PEP include the fact that `? and `??` have been in use in the Scientific
Python community for 10 to 14 years now, and that any Scientific Python user who
have touched IPython will tell you that ? and ?? are for getting help.
(?? try to pull the source, while ? does not, but let's not get into details).
This include the fact that any IDE (like spyder) which use IPython under
the hood have this feature.
The usage of `?` is even visible on Python.org main page [3] (imgur screenshot),
which invite the user to launch an interactive console saying:
> object? -> Details about 'object', use 'object??' for extra details.
> In [1]:
leading the casual user thinking that this is a Python feature.
This fact is even including in Books and introduction to python. Sometime
without mentioning that the feature is IPython Specific, and does not work in
Python repl/scripts.
Examples in Cyrile's rossant "Learning IPython for Interactive
Computing and Data Visualization"[1]
introduce Python with the second code/repl example beeing about `?`.
Book extract :
> Some of these commands let you get some help or information about any
> Python function or object. For instance, have you ever had a doubt about how
> to use the super function to access parent methods in a derived class? Just type
> `super?` and you’ll find out. Appending `?` to any command or variable gives you all
> the information you need about it.
> In [1]: super?
> Type: type
> String Form:<type 'super'>
> Namespace: Python builtin
> ...
A google search also give for eaxample:
Python for beginners online tutorial[2] which does rapidly the same:
Tuto snippet:
> The "?" is very useful. If you type in `?` after a `len?`, you will see the
> documentation about the function len.
> Typing `?` after a name will give you information about the object attached to that name.
Doing even worse as they replace the IPython prompt `In[x]:` with
`>>>` literally showing
that `>>> len?` works. Which imply that it should work on a plain Python REPL.
As someone that have to regularly teach Python, and interact with new
Python users,
it will be hard to explain that `?` and `??` have different meaning
depending on the context,
and that most book on Scientific Python are wrong/inaccurate.
From the current state of the PEP/proposal I'm guessing we should be
able to distinguish
Null Coalescing operation (or whatever name you want to give them) in
Python 3.6+
from actual help request, and that this will allow us to keep backward
compatibility
with 10+ years of code/user habits, but the result will most likely be
confusing.
It will be even harder if we have to remove the usage of `?`/`??`[4].
I also want to note that the use of `?`/`??` is not present to just being or end
of identifiers as it can also be used use to search for names:
> In [1]: *int*?
> FloatingPointError
> int
> print
But this usage is not as widespread as extracting help about objects,
and seem less relevant, though I'm not sure:
> In [10]: ?Float*Error
> FloatingPointError
>
> In [12]: Uni*Error?
> UnicodeDecodeError
> UnicodeEncodeError
> UnicodeError
> UnicodeTranslateError
Please take these fact into consideration when making a
decision/writing the Pep.
Thanks,
--
M
[1]: That's one of the only book for which I have (legally) the
sources, and that I bother to grepped through.
[2]: http://www.pythonforbeginners.com/basics/ipython-a-short-introduction
[3]: http://imgur.com/d0Vs7Xr
[4]: I'll have to hire a body guard to prevent people to pursue me to
the end of the earth with a chainsaw. I'm sure you know that feeling.