What's the status of PEP 505: None-aware operators?
Hi Mark, it looks like the PEP is dormant for over two years now. I had multiple people ask me over the past few days about it though, so I wanted to ask if this is moving forward. I also cc python-dev to see if anybody here is strongly in favor or against this inclusion. If the idea itself is uncontroversial, I could likely find somebody interested in implementing it. If not for 3.7 then at least for 3.8. - Ł
Please, not for 3.7. I think it will be very difficult to get consensus
about this, and I personally feel something like +/- zero about it --
sometimes I think it makes sense, sometimes I think we're jumping the shark
here.
On Tue, Nov 28, 2017 at 12:10 PM, Lukasz Langa
Hi Mark, it looks like the PEP is dormant for over two years now. I had multiple people ask me over the past few days about it though, so I wanted to ask if this is moving forward.
I also cc python-dev to see if anybody here is strongly in favor or against this inclusion. If the idea itself is uncontroversial, I could likely find somebody interested in implementing it. If not for 3.7 then at least for 3.8.
- Ł
_______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/ guido%40python.org
-- --Guido van Rossum (python.org/~guido)
On 29 November 2017 at 06:17, Guido van Rossum
Please, not for 3.7. I think it will be very difficult to get consensus about this, and I personally feel something like +/- zero about it -- sometimes I think it makes sense, sometimes I think we're jumping the shark here.
I've marked all 3 of the related PEPs as Deferred until 3.8 at the earliest: https://github.com/python/peps/commit/181cc79af925e06a068733a1419b1760ac1a2d... PEP 505: None-aware operators PEP 532: A circuit breaking protocol and binary operators PEP 535: Rich comparison chaining I don't see any urgency to resolve any of them - the None-aware operators do make certain kinds of code (commonly found in JSON processing) easier to read and write, but such code is still fairly readable and writable today (it's just a bit verbose and boilerplate heavy), and the other two PEPs arise specifically from seeking to provide a common conceptual underpinning for the semantics of both the proposed None-aware operations and the existing short-circuiting logical operators. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia
I also cc python-dev to see if anybody here is strongly in favor or against this inclusion.
Put me down for a strong -1. The proposal would occasionally save a few keystokes but comes at the expense of giving Python a more Perlish look and a more arcane feel. One of the things I like about Python is that I can walk non-programmers through the code and explain what it does. The examples in PEP 505 look like a step in the wrong direction. They don't "look like Python" and make me feel like I have to decrypt the code to figure-out what it does. timeout ?? local_timeout ?? global_timeout 'foo' in (None ?? ['foo', 'bar']) requested_quantity ?? default_quantity * price name?.strip()[4:].upper() user?.first_name.upper() Raymond
On Nov 28, 2017, at 15:31, Raymond Hettinger
Put me down for a strong -1. The proposal would occasionally save a few keystokes but comes at the expense of giving Python a more Perlish look and a more arcane feel.
I am also -1.
One of the things I like about Python is that I can walk non-programmers through the code and explain what it does. The examples in PEP 505 look like a step in the wrong direction. They don't "look like Python" and make me feel like I have to decrypt the code to figure-out what it does.
I had occasional to speak with someone very involved in Rust development. They have a process roughly similar to our PEPs. One of the things he told me, which I found very interesting and have been mulling over for PEPs is, they require a section in their specification discussion how any new feature will be taught, both to new Rust programmers and experienced ones. I love the emphasis on teachability. Sometimes I really miss that when considering some of the PEPs and the features they introduce (look how hard it is to teach asynchronous programming). Cheers, -Barry
-1 from me too.
Mariatta Wijaya
On Tue, Nov 28, 2017 at 12:38 PM, Barry Warsaw
On Nov 28, 2017, at 15:31, Raymond Hettinger
wrote: Put me down for a strong -1. The proposal would occasionally save a few keystokes but comes at the expense of giving Python a more Perlish look and a more arcane feel.
I am also -1.
One of the things I like about Python is that I can walk non-programmers through the code and explain what it does. The examples in PEP 505 look like a step in the wrong direction. They don't "look like Python" and make me feel like I have to decrypt the code to figure-out what it does.
I had occasional to speak with someone very involved in Rust development. They have a process roughly similar to our PEPs. One of the things he told me, which I found very interesting and have been mulling over for PEPs is, they require a section in their specification discussion how any new feature will be taught, both to new Rust programmers and experienced ones. I love the emphasis on teachability. Sometimes I really miss that when considering some of the PEPs and the features they introduce (look how hard it is to teach asynchronous programming).
Cheers, -Barry
_______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/ mariatta.wijaya%40gmail.com
On 28 November 2017 at 20:38, Barry Warsaw
On Nov 28, 2017, at 15:31, Raymond Hettinger
wrote: Put me down for a strong -1. The proposal would occasionally save a few keystokes but comes at the expense of giving Python a more Perlish look and a more arcane feel.
I am also -1.
-1 from me, too.
One of the things I like about Python is that I can walk non-programmers through the code and explain what it does. The examples in PEP 505 look like a step in the wrong direction. They don't "look like Python" and make me feel like I have to decrypt the code to figure-out what it does.
I had occasional to speak with someone very involved in Rust development. They have a process roughly similar to our PEPs. One of the things he told me, which I found very interesting and have been mulling over for PEPs is, they require a section in their specification discussion how any new feature will be taught, both to new Rust programmers and experienced ones. I love the emphasis on teachability. Sometimes I really miss that when considering some of the PEPs and the features they introduce (look how hard it is to teach asynchronous programming).
That's a really nice idea. I'd like to see Python adopt something similar (even just as a guideline on how to write a PEP). Paul
On Nov 28, 2017, at 15:59, Paul Moore
wrote: On 28 November 2017 at 20:38, Barry Warsaw
wrote:
I had occasional to speak with someone very involved in Rust development. They have a process roughly similar to our PEPs. One of the things he told me, which I found very interesting and have been mulling over for PEPs is, they require a section in their specification discussion how any new feature will be taught, both to new Rust programmers and experienced ones. I love the emphasis on teachability. Sometimes I really miss that when considering some of the PEPs and the features they introduce (look how hard it is to teach asynchronous programming).
That's a really nice idea. I'd like to see Python adopt something similar (even just as a guideline on how to write a PEP).
On 28 November 2017 at 18:38, Barry Warsaw
On Nov 28, 2017, at 15:31, Raymond Hettinger
wrote: Put me down for a strong -1. The proposal would occasionally save a few keystokes but comes at the expense of giving Python a more Perlish look and a more arcane feel.
I am also -1.
One of the things I like about Python is that I can walk non-programmers through the code and explain what it does. The examples in PEP 505 look like a step in the wrong direction. They don't "look like Python" and make me feel like I have to decrypt the code to figure-out what it does.
I had occasional to speak with someone very involved in Rust development. They have a process roughly similar to our PEPs. One of the things he told me, which I found very interesting and have been mulling over for PEPs is, they require a section in their specification discussion how any new feature will be taught, both to new Rust programmers and experienced ones. I love the emphasis on teachability. Sometimes I really miss that when considering some of the PEPs and the features they introduce (look how hard it is to teach asynchronous programming).
Oh well, I would be +1 on patching PEP 1 for that.
Cheers, -Barry
Not really related but the PEP says that arguments in Python are evaluated
before the function (as a reason to reject the idea of None-aware function
call) but this is not the case:
>>> import dis
>>> dis.dis(lambda : f()(g()))
1 0 LOAD_GLOBAL 0 (f)
3 CALL_FUNCTION 0
6 LOAD_GLOBAL 1 (g)
9 CALL_FUNCTION 0
12 CALL_FUNCTION 1
15 RETURN_VALUE
Andrea
On Wed, Nov 29, 2017 at 7:14 PM, Joao S. O. Bueno
On Nov 28, 2017, at 15:31, Raymond Hettinger < raymond.hettinger@gmail.com> wrote:
Put me down for a strong -1. The proposal would occasionally save a few keystokes but comes at the expense of giving Python a more Perlish look and a more arcane feel.
I am also -1.
One of the things I like about Python is that I can walk non-programmers through the code and explain what it does. The examples in PEP 505 look like a step in the wrong direction. They don't "look like Python" and make me feel like I have to decrypt the code to figure-out what it does.
I had occasional to speak with someone very involved in Rust development. They have a process roughly similar to our PEPs. One of the
On 28 November 2017 at 18:38, Barry Warsaw
wrote: things he told me, which I found very interesting and have been mulling over for PEPs is, they require a section in their specification discussion how any new feature will be taught, both to new Rust programmers and experienced ones. I love the emphasis on teachability. Sometimes I really miss that when considering some of the PEPs and the features they introduce (look how hard it is to teach asynchronous programming). Oh well, I would be +1 on patching PEP 1 for that.
Cheers, -Barry
_______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/ agriff%40tin.it
On Thu, Nov 30, 2017 at 2:48 AM, Andrea Griffini
Not really related but the PEP says that arguments in Python are evaluated before the function (as a reason to reject the idea of None-aware function call) but this is not the case:
I think you're missing something here, since it seems clear to me that indeed the arguments are evaluated prior to the function call. Maybe unrolling it would help? This is equivalent to the body of your lambda, and you can see that the argument is evaluated prior to the call which receives it.
func = f() arg = g() func(arg)
>>> import dis
>>> dis.dis(lambda : f()(g())) 1 0 LOAD_GLOBAL 0 (f) 3 CALL_FUNCTION 0
Call 'f()' with all of its arguments evaluated prior to the call (there are none, that's the '0' on the CALL_FUNCTION operator).
6 LOAD_GLOBAL 1 (g) 9 CALL_FUNCTION 0
Next, evaluate the arguments for the next function call. Call 'g()' with all of its arguments evaluated.
12 CALL_FUNCTION 1
Call the function that 'f()' returned with its argument ('g()') evaluated.
On Thu, Nov 30, 2017, at 11:08, Eric Fahlgren wrote:
On Thu, Nov 30, 2017 at 2:48 AM, Andrea Griffini
wrote: Not really related but the PEP says that arguments in Python are evaluated before the function (as a reason to reject the idea of None-aware function call) but this is not the case:
I think you're missing something here, since it seems clear to me that indeed the arguments are evaluated prior to the function call. Maybe unrolling it would help? This is equivalent to the body of your lambda, and you can see that the argument is evaluated prior to the call which receives it.
Of course they're evaluated prior to the function *call*, but the pep says they're evaluated prior to the function *itself* [i.e. arg = g(); func = f(); func(arg)].
Eric Fahlgren wrote:
I think you're missing something here, since it seems clear to me that indeed the arguments are evaluated prior to the function call.
I think the OP may be confusing "evaluating the function" with "calling the function". If the function being called is determined by some computation, that computation may be performed before its arguments are evaluated (and is probably required to be, by the "left to right" rule). But the arguments will always be evaluated before the actual call happens. -- Greg
On Thu, Nov 30, 2017, at 17:26, Greg Ewing wrote:
Eric Fahlgren wrote:
I think you're missing something here, since it seems clear to me that indeed the arguments are evaluated prior to the function call.
I think the OP may be confusing "evaluating the function" with "calling the function".
If the function being called is determined by some computation, that computation may be performed before its arguments are evaluated (and is probably required to be, by the "left to right" rule). But the arguments will always be evaluated before the actual call happens.
Right, but if the function is evaluated before either of those things happen, then it can indeed short-circuit the argument evaluation. The OP isn't confusing anything; it's Eric who is confused. The quoted paragraph of the PEP clearly and unambiguously claims that the sequence is "arguments -> function -> call", meaning that something happens after the "function" stage [i.e. a None check] cannot short-circuit the "arguments" stage. But in fact the sequence is "function -> arguments -> call".
On Thu, Nov 30, 2017 at 11:54:39PM -0500, Random832 wrote:
The OP isn't confusing anything; it's Eric who is confused. The quoted paragraph of the PEP clearly and unambiguously claims that the sequence is "arguments -> function -> call", meaning that something happens after the "function" stage [i.e. a None check] cannot short-circuit the "arguments" stage. But in fact the sequence is "function -> arguments -> call".
I'm more confused than ever. You seem to be arguing that Python functions CAN short-circuit their arguments and avoid evaluating them. Is that the case? If not, then I fail to see the difference between "arguments -> function -> call" "function -> arguments -> call" In *both cases* the arguments are fully evaluated before the function is called, and so there is nothing the function can do to delay evaluating its arguments. If this is merely about when the name "function" is looked up, then I don't see why that's relevant to the PEP. What am I missing? -- Steve
On Thu, Nov 30, 2017 at 11:54:39PM -0500, Random832 wrote:
The OP isn't confusing anything; it's Eric who is confused. The quoted paragraph of the PEP clearly and unambiguously claims that the sequence is "arguments -> function -> call", meaning that something happens after the "function" stage [i.e. a None check] cannot short-circuit the "arguments" stage. But in fact the sequence is "function -> arguments -> call".
I'm more confused than ever. You seem to be arguing that Python functions CAN short-circuit their arguments and avoid evaluating them. Is that the case?
If not, then I fail to see the difference between
"arguments -> function -> call"
"function -> arguments -> call"
In *both cases* the arguments are fully evaluated before the function is called, and so there is nothing the function can do to delay evaluating its arguments.
If this is merely about when the name "function" is looked up, then I don't see why that's relevant to the PEP.
What am I missing?
I guess it's possible that if computing the function (i.e., evaluating
On Fri, Dec 1, 2017 at 10:31 AM, Steven D'Aprano
On Fri, Dec 1, 2017, at 05:31, Steven D'Aprano wrote:
I'm more confused than ever. You seem to be arguing that Python functions CAN short-circuit their arguments and avoid evaluating them. Is that the case?
If this is merely about when the name "function" is looked up, then I don't see why that's relevant to the PEP.
What am I missing?
You're completely missing the context of the discussion, which was the supposed reason that a *new* function call operator, with the proposed syntax function?(args), that would short-circuit (based on the 'function' being None) could not be implemented. The whole thing doesn't make sense to me anyway, since a new operator could have its own sequence different from the existing one if necessary.
On Fri, Dec 1, 2017 at 5:24 AM, Random832
You're completely missing the context of the discussion, which was the supposed reason that a *new* function call operator, with the proposed syntax function?(args), that would short-circuit (based on the 'function' being None) could not be implemented. The whole thing doesn't make sense to me anyway, since a new operator could have its own sequence different from the existing one if necessary.
Right, I was clearly misinterpreting the wording in the PEP. It's a bit ambiguous and should probably make explicit that "evaluate the function" isn't just the common vernacular for "call the function".
On 2017-12-01 13:24, Random832 wrote:
On Fri, Dec 1, 2017, at 05:31, Steven D'Aprano wrote:
I'm more confused than ever. You seem to be arguing that Python functions CAN short-circuit their arguments and avoid evaluating them. Is that the case?
If this is merely about when the name "function" is looked up, then I don't see why that's relevant to the PEP.
What am I missing?
You're completely missing the context of the discussion, which was the supposed reason that a *new* function call operator, with the proposed syntax function?(args), that would short-circuit (based on the 'function' being None) could not be implemented. The whole thing doesn't make sense to me anyway, since a new operator could have its own sequence different from the existing one if necessary.
The code: function?(args) would be equivalent to: None if function is None else function(args) where 'function' would be evaluated once. If function is None, the arguments would not be evaluated.
On Fri, Dec 01, 2017 at 08:24:05AM -0500, Random832 wrote:
On Fri, Dec 1, 2017, at 05:31, Steven D'Aprano wrote:
I'm more confused than ever. You seem to be arguing that Python functions CAN short-circuit their arguments and avoid evaluating them. Is that the case?
If this is merely about when the name "function" is looked up, then I don't see why that's relevant to the PEP.
What am I missing?
You're completely missing the context of the discussion,
Yes I am. That's why I asked.
which was the supposed reason that a *new* function call operator, with the proposed syntax function?(args), that would short-circuit (based on the 'function' being None) could not be implemented.
Given that neither your post (which I replied to) nor the post you were replying to mentioned anything about function?() syntax, perhaps I might be forgiven for having no idea what you were talking about? The PEP only mentions function?() as a rejected idea, do I don't know why we're even talking about it. The PEP is deferred, with considerable opposition and luke-warm support, even the PEP author has said he's not going to push for it, and we're arguing about a pedantic point related to a part of the PEP which is rejected... :-) -- Steve
On 2 December 2017 at 12:01, Steven D'Aprano
The PEP only mentions function?() as a rejected idea, do I don't know why we're even talking about it. The PEP is deferred, with considerable opposition and luke-warm support, even the PEP author has said he's not going to push for it, and we're arguing about a pedantic point related to a part of the PEP which is rejected...
Nevertheless, I've fixed the rationale for that decision so folks don't get hung up on the mistake in the previously noted rationale: https://github.com/python/peps/commit/966dd426787e6de8ec6218955cec57f65086c5... Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia
The PEP says that a None-aware function call operator (e.g. "f?(x, y)")
would break the rule of python that arguments are evaluated before the
function but this is not correct.
In Python the function is evaluated before the arguments (but of course the
CALL is made after the evaluation of the arguments).
A None-aware function call operator ?(...) wouldn't break this order of
evaluation rule: 1) evaluate the function, 2) only if it's not None
evaluate arguments and make the call.
In bytecode the None-aware function call would simply require a extra
"JNONE" to the end...
... evaluate the function ...
JNONE skip
... evaluate arguments ...
CALL n
skip:
Note that I'm not saying this would be a good thing, just that the reason
the PEP uses to dismiss this option is actually wrong because Python
doesn't work the way the PEP says it does.
Andrea
On Fri, Dec 1, 2017 at 11:31 AM, Steven D'Aprano
On Thu, Nov 30, 2017 at 11:54:39PM -0500, Random832 wrote:
The OP isn't confusing anything; it's Eric who is confused. The quoted paragraph of the PEP clearly and unambiguously claims that the sequence is "arguments -> function -> call", meaning that something happens after the "function" stage [i.e. a None check] cannot short-circuit the "arguments" stage. But in fact the sequence is "function -> arguments -> call".
I'm more confused than ever. You seem to be arguing that Python functions CAN short-circuit their arguments and avoid evaluating them. Is that the case?
If not, then I fail to see the difference between
"arguments -> function -> call"
"function -> arguments -> call"
In *both cases* the arguments are fully evaluated before the function is called, and so there is nothing the function can do to delay evaluating its arguments.
If this is merely about when the name "function" is looked up, then I don't see why that's relevant to the PEP.
What am I missing?
-- Steve _______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/ agriff%40tin.it
On 2017-11-28 21:31, Raymond Hettinger wrote:
I also cc python-dev to see if anybody here is strongly in favor or against this inclusion.
Put me down for a strong -1. The proposal would occasionally save a few keystokes but comes at the expense of giving Python a more Perlish look and a more arcane feel.
One of the things I like about Python is that I can walk non-programmers through the code and explain what it does. The examples in PEP 505 look like a step in the wrong direction. They don't "look like Python" and make me feel like I have to decrypt the code to figure-out what it does.
timeout ?? local_timeout ?? global_timeout 'foo' in (None ?? ['foo', 'bar']) requested_quantity ?? default_quantity * price name?.strip()[4:].upper() user?.first_name.upper()
Your examples have convinced me, -1 from me.
Hi Lukasz, I don’t have plans on editing or promoting the PEP any further, unless there is renewed interest or somebody proposes a more Pythonic syntax. -- Mark E. Haase
On Nov 28, 2017, at 3:31 PM, Raymond Hettinger
wrote: I also cc python-dev to see if anybody here is strongly in favor or against this inclusion.
Put me down for a strong -1. The proposal would occasionally save a few keystokes but comes at the expense of giving Python a more Perlish look and a more arcane feel.
One of the things I like about Python is that I can walk non-programmers through the code and explain what it does. The examples in PEP 505 look like a step in the wrong direction. They don't "look like Python" and make me feel like I have to decrypt the code to figure-out what it does.
timeout ?? local_timeout ?? global_timeout 'foo' in (None ?? ['foo', 'bar']) requested_quantity ?? default_quantity * price name?.strip()[4:].upper() user?.first_name.upper()
Raymond
On 29 November 2017 at 07:15, Mark Haase
Hi Lukasz, I don’t have plans on editing or promoting the PEP any further, unless there is renewed interest or somebody proposes a more Pythonic syntax.
We should probably set the state of both this and the related circuit breaking protocol PEPs to Deferred so folks know neither of us is actually working on them. While I still think there's merit to the idea of making it easier to write concise data cleanup pipelines in Python, I find the argument "The currently proposed spelling doesn't even come close to reading like executable pseudo code" to be a compelling one. I think a big part of the problem is that these kinds of data cleanup operations don't even have a good *vocabulary* around them yet, so nobody actually knows how to write them as pseudo code in the first place - we only know how to express them in particular programming languages. Trying to come up with pseudo code for the example cases Raymond mentioned: timeout if defined, else local_timeout if defined, else global_timeout price * (requested_quantity if defined, else default_quantity) name if not defined, else name.strip()[4:].upper() user if not defined, else name.first_name.upper() And that's not actually that different to their current spellings in Python: timeout if timeout is not None else local_timeout if local_timeout is not None, else global_timeout price * (requested_quantity if requested_quantity is not None else default_quantity) name if name is None else name.strip()[4:].upper() user if user is None else name.first_name.upper() One key aspect that Python does miss relative to the pseudocode versions is that we don't actually have a term for "expr is not None". "def" is used specifically for functions, so "defined" isn't reference right. References to "None" are bound like anything else, so "bound" isn't right. "exists" probably comes closest (hence the title of the withdrawn PEP 531). That said, if we did decide to allow "def" in a conditional expression to mean "defined" in the "lhs is not None" sense, it would look like: timeout if def else local_timeout if def else global_timeout price * (requested_quantity if def else default_quantity) name if not def else name.strip()[4:].upper() user if not def else user.first_name.upper() Cheers, Nick. P.S. Compared to this, our last symbolic feature addition (matrix multiplication), was a relatively straightforward transcription of "⋅" to "@", just as regular multiplication is a transcription of "×" to "*". -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia
28.11.17 22:31, Raymond Hettinger пише:
I also cc python-dev to see if anybody here is strongly in favor or against this inclusion.
Put me down for a strong -1. The proposal would occasionally save a few keystokes but comes at the expense of giving Python a more Perlish look and a more arcane feel.
One of the things I like about Python is that I can walk non-programmers through the code and explain what it does. The examples in PEP 505 look like a step in the wrong direction. They don't "look like Python" and make me feel like I have to decrypt the code to figure-out what it does.
timeout ?? local_timeout ?? global_timeout 'foo' in (None ?? ['foo', 'bar']) requested_quantity ?? default_quantity * price name?.strip()[4:].upper() user?.first_name.upper()
New syntax often look unusual. "lambda" and "yield" also didn't "look like Python". But there are other considerations. 1. Languages that has the ?? and ?. operators usually have a single special (or at least a one obvious) value that is served for signaling "there-is-no-a-value". The None in Python is not so special. It can be used as a common object, and other ways can be used for denoting an "absent" value. The need of None-specific operators in Python is lower. 2. Python already have other ways for handling "absent" values: the short-circuit "or" and "and" operators which return the one of arguments, getattr() with the default value, the hack with default class attributes, exception handling. The need of the proposed operators in Python is lower. 3. These languages usually have borrowed the syntax of the ternary operator from C: "... ? ... : ...". Thus the syntax with "?" looks more natural in them. But in Python it looks less natural. I'm -1 for accepting this syntax in 3.7. In future all can be changed.
On Tue, Nov 28, 2017, at 15:31, Raymond Hettinger wrote:
I also cc python-dev to see if anybody here is strongly in favor or against this inclusion.
Put me down for a strong -1. The proposal would occasionally save a few keystokes but comes at the expense of giving Python a more Perlish look and a more arcane feel.
One of the things I like about Python is that I can walk non-programmers through the code and explain what it does. The examples in PEP 505 look like a step in the wrong direction. They don't "look like Python" and make me feel like I have to decrypt the code to figure-out what it does.
timeout ?? local_timeout ?? global_timeout 'foo' in (None ?? ['foo', 'bar']) requested_quantity ?? default_quantity * price name?.strip()[4:].upper() user?.first_name.upper()
Since we're looking at different syntax for the ?? operator, I have a suggestion for the ?. operator - and related ?[] and ?() that appeared in some of the proposals. How about this approach? Something like (or None: ...) as a syntax block in which any operation [lexically within the expression, not within e.g. called functions, so it's different from simply catching AttributeError etc, even if that could be limited to only catching when the operand is None] on None that is not valid for None will yield None instead. This isn't *entirely* equivalent, but offers finer control. v = name?.strip()[4:].upper() under the old proposal would be more or less equivalent to: v = name.strip()[4:].upper() if name is not None else None Whereas, you could get the same result with: (or None: name.strip()[4:].upper()) Though that would technically be equivalent to these steps: v = name.strip if name is not None else None v = v() if v """"" v = v[4:] """"""" v = v.upper """"""" v = v() """"""" The compiler could optimize this case since it knows none of the operations are valid on None. This has the advantage of being explicit about what scope the modified rules apply to, rather than simply implicitly being "to the end of the chain of dot/bracket/call operators" It could also be extended to apply, without any additional syntax, to binary operators (result is None if either operand is None) (or None: a + b), for example, could return None if either a or b is none. [I think I proposed this before with the syntax ?(...), the (or None: ...) is just an idea to make it look more like Python.]
I like much of the thinking in Random's approach. But I still think None
isn't quite special enough to warrant it's own syntax.
However, his '(or None: name.strip()[4:].upper())' makes me realize that
what is being asked in all the '?(', '?.', '?[' syntax ideas is a kind of
ternary expression. Except the ternary isn't based on whether a predicate
holds, but rather on whether an exception occurs (AttributeError, KeyError,
TypeError). And the fallback in the ternary is always None rather than
being general.
I think we could generalize this to get something both more Pythonic and
more flexible. E.g.:
val = name.strip()[4:].upper() except None
This would just be catching all errors, which is perhaps too broad. But it
*would* allow a fallback other than None:
val = name.strip()[4:].upper() except -1
I think some syntax could be possible to only "catch" some exceptions and
let others propagate. Maybe:
val = name.strip()[4:].upper() except (AttributeError, KeyError): -1
I don't really like throwing a colon in an expression though. Perhaps some
other word or symbol could work instead. How does this read:
val = name.strip()[4:].upper() except -1 in (AttributeError, KeyError)
Where the 'in' clause at the end would be optional, and default to
'Exception'.
I'll note that what this idea DOES NOT get us is:
val = timeout ?? local_timeout ?? global_timeout
Those values that are "possibly None" don't raise exceptions, so they
wouldn't apply to this syntax.
Yours, David...
On Wed, Nov 29, 2017 at 9:03 AM, Random832
On Tue, Nov 28, 2017, at 15:31, Raymond Hettinger wrote:
I also cc python-dev to see if anybody here is strongly in favor or
against this inclusion.
Put me down for a strong -1. The proposal would occasionally save a few keystokes but comes at the expense of giving Python a more Perlish look and a more arcane feel.
One of the things I like about Python is that I can walk non-programmers through the code and explain what it does. The examples in PEP 505 look like a step in the wrong direction. They don't "look like Python" and make me feel like I have to decrypt the code to figure-out what it does.
timeout ?? local_timeout ?? global_timeout 'foo' in (None ?? ['foo', 'bar']) requested_quantity ?? default_quantity * price name?.strip()[4:].upper() user?.first_name.upper()
Since we're looking at different syntax for the ?? operator, I have a suggestion for the ?. operator - and related ?[] and ?() that appeared in some of the proposals. How about this approach?
Something like (or None: ...) as a syntax block in which any operation [lexically within the expression, not within e.g. called functions, so it's different from simply catching AttributeError etc, even if that could be limited to only catching when the operand is None] on None that is not valid for None will yield None instead.
This isn't *entirely* equivalent, but offers finer control.
v = name?.strip()[4:].upper() under the old proposal would be more or less equivalent to:
v = name.strip()[4:].upper() if name is not None else None
Whereas, you could get the same result with: (or None: name.strip()[4:].upper())
Though that would technically be equivalent to these steps: v = name.strip if name is not None else None v = v() if v """"" v = v[4:] """"""" v = v.upper """"""" v = v() """""""
The compiler could optimize this case since it knows none of the operations are valid on None. This has the advantage of being explicit about what scope the modified rules apply to, rather than simply implicitly being "to the end of the chain of dot/bracket/call operators"
It could also be extended to apply, without any additional syntax, to binary operators (result is None if either operand is None) (or None: a + b), for example, could return None if either a or b is none.
[I think I proposed this before with the syntax ?(...), the (or None: ...) is just an idea to make it look more like Python.] _______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/ mertz%40gnosis.cx
-- Keeping medicines from the bloodstreams of the sick; food from the bellies of the hungry; books from the hands of the uneducated; technology from the underdeveloped; and putting advocates of freedom in prisons. Intellectual property is to the 21st century what the slave trade was to the 16th.
On Nov 29, 2017, at 12:40 PM, David Mertz
wrote: I like much of the thinking in Random's approach. But I still think None isn't quite special enough to warrant it's own syntax.
However, his '(or None: name.strip()[4:].upper())' makes me realize that what is being asked in all the '?(', '?.', '?[' syntax ideas is a kind of ternary expression. Except the ternary isn't based on whether a predicate holds, but rather on whether an exception occurs (AttributeError, KeyError, TypeError). And the fallback in the ternary is always None rather than being general.
I think we could generalize this to get something both more Pythonic and more flexible. E.g.:
val = name.strip()[4:].upper() except None
This would just be catching all errors, which is perhaps too broad. But it *would* allow a fallback other than None:
val = name.strip()[4:].upper() except -1
I think some syntax could be possible to only "catch" some exceptions and let others propagate. Maybe:
val = name.strip()[4:].upper() except (AttributeError, KeyError): -1
I don't really like throwing a colon in an expression though. Perhaps some other word or symbol could work instead. How does this read:
val = name.strip()[4:].upper() except -1 in (AttributeError, KeyError)
Where the 'in' clause at the end would be optional, and default to 'Exception'.
I'll note that what this idea DOES NOT get us is:
val = timeout ?? local_timeout ?? global_timeout
Those values that are "possibly None" don't raise exceptions, so they wouldn't apply to this syntax.
See the rejected PEP 463 for Exception catching expressions. Eric.
Yours, David...
On Wed, Nov 29, 2017 at 9:03 AM, Random832
wrote: On Tue, Nov 28, 2017, at 15:31, Raymond Hettinger wrote: I also cc python-dev to see if anybody here is strongly in favor or against this inclusion.
Put me down for a strong -1. The proposal would occasionally save a few keystokes but comes at the expense of giving Python a more Perlish look and a more arcane feel.
One of the things I like about Python is that I can walk non-programmers through the code and explain what it does. The examples in PEP 505 look like a step in the wrong direction. They don't "look like Python" and make me feel like I have to decrypt the code to figure-out what it does.
timeout ?? local_timeout ?? global_timeout 'foo' in (None ?? ['foo', 'bar']) requested_quantity ?? default_quantity * price name?.strip()[4:].upper() user?.first_name.upper()
Since we're looking at different syntax for the ?? operator, I have a suggestion for the ?. operator - and related ?[] and ?() that appeared in some of the proposals. How about this approach?
Something like (or None: ...) as a syntax block in which any operation [lexically within the expression, not within e.g. called functions, so it's different from simply catching AttributeError etc, even if that could be limited to only catching when the operand is None] on None that is not valid for None will yield None instead.
This isn't *entirely* equivalent, but offers finer control.
v = name?.strip()[4:].upper() under the old proposal would be more or less equivalent to:
v = name.strip()[4:].upper() if name is not None else None
Whereas, you could get the same result with: (or None: name.strip()[4:].upper())
Though that would technically be equivalent to these steps: v = name.strip if name is not None else None v = v() if v """"" v = v[4:] """"""" v = v.upper """"""" v = v() """""""
The compiler could optimize this case since it knows none of the operations are valid on None. This has the advantage of being explicit about what scope the modified rules apply to, rather than simply implicitly being "to the end of the chain of dot/bracket/call operators"
It could also be extended to apply, without any additional syntax, to binary operators (result is None if either operand is None) (or None: a + b), for example, could return None if either a or b is none.
[I think I proposed this before with the syntax ?(...), the (or None: ...) is just an idea to make it look more like Python.] _______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/mertz%40gnosis.cx
-- Keeping medicines from the bloodstreams of the sick; food from the bellies of the hungry; books from the hands of the uneducated; technology from the underdeveloped; and putting advocates of freedom in prisons. Intellectual property is to the 21st century what the slave trade was to the 16th. _______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/eric%2Ba-python-dev%40tru...
On Nov 29, 2017, at 12:40, David Mertz
I think some syntax could be possible to only "catch" some exceptions and let others propagate. Maybe:
val = name.strip()[4:].upper() except (AttributeError, KeyError): -1
I don't really like throwing a colon in an expression though. Perhaps some other word or symbol could work instead. How does this read:
val = name.strip()[4:].upper() except -1 in (AttributeError, KeyError)
I don’t know whether I like any of this <wink> but I think a more natural spelling would be: val = name.strip()[4:].upper() except (AttributeError, KeyError) as -1 which could devolve into: val = name.strip()[4:].upper() except KeyError as -1 or: val = name.strip()[4:].upper() except KeyError # Implicit `as None` I would *not* add any spelling for an explicit bare-except equivalent. You would have to write: val = name.strip()[4:].upper() except Exception as -1 Cheers, -Barry
On 11/29/2017 01:02 PM, Barry Warsaw wrote:
I don’t know whether I like any of this <wink> but I think a more natural spelling would be:
val = name.strip()[4:].upper() except (AttributeError, KeyError) as -1
which could devolve into:
val = name.strip()[4:].upper() except KeyError as -1
or:
val = name.strip()[4:].upper() except KeyError # Implicit `as None`
Of all the proposed spellings for the idea, this one feels most "normal" to me, too (I'm -0 on the idea as a whole).
I would *not* add any spelling for an explicit bare-except equivalent. You would have to write:
val = name.strip()[4:].upper() except Exception as -1
Wouldn't that really need to be this instead, for a true 'except:' equivalence: val = name.strip()[4:].upper() except BaseException as -1 Tres. -- =================================================================== Tres Seaver +1 540-429-0999 tseaver@palladion.com Palladion Software "Excellence by Design" http://palladion.com
On Fri, Dec 1, 2017 at 5:45 AM, Tres Seaver
I would *not* add any spelling for an explicit bare-except equivalent. You would have to write:
val = name.strip()[4:].upper() except Exception as -1
Wouldn't that really need to be this instead, for a true 'except:' equivalence:
val = name.strip()[4:].upper() except BaseException as -1
Read the rejected PEP 463 for all the details and arguments. All this has been gone into. ChrisA
Le 29/11/2017 à 19:02, Barry Warsaw a écrit :
On Nov 29, 2017, at 12:40, David Mertz
wrote: I think some syntax could be possible to only "catch" some exceptions and let others propagate. Maybe:
val = name.strip()[4:].upper() except (AttributeError, KeyError): -1
I don't really like throwing a colon in an expression though. Perhaps some other word or symbol could work instead. How does this read:
val = name.strip()[4:].upper() except -1 in (AttributeError, KeyError)
I don’t know whether I like any of this <wink> but I think a more natural spelling would be:
val = name.strip()[4:].upper() except (AttributeError, KeyError) as -1
which could devolve into:
val = name.strip()[4:].upper() except KeyError as -1
or:
val = name.strip()[4:].upper() except KeyError # Implicit `as None`
I would *not* add any spelling for an explicit bare-except equivalent. You would have to write:
val = name.strip()[4:].upper() except Exception as -1
Cheers, -Barry
I really like this one. It's way more general. I can see a use for IndexError as well (lists don't have the dict.get() method). Also I would prefer not to use "as" this way. In the context of an exception, "as" already binds the exception to a variable so it's confusing. What about: val = name.strip()[4:].upper() except Exception: -1
On Tue, Dec 12, 2017 at 7:39 PM, Michel Desmoulin
Le 29/11/2017 à 19:02, Barry Warsaw a écrit :
On Nov 29, 2017, at 12:40, David Mertz
wrote: I think some syntax could be possible to only "catch" some exceptions and let others propagate. Maybe:
val = name.strip()[4:].upper() except (AttributeError, KeyError): -1
I don't really like throwing a colon in an expression though. Perhaps some other word or symbol could work instead. How does this read:
val = name.strip()[4:].upper() except -1 in (AttributeError, KeyError)
I don’t know whether I like any of this <wink> but I think a more natural spelling would be:
val = name.strip()[4:].upper() except (AttributeError, KeyError) as -1
which could devolve into:
val = name.strip()[4:].upper() except KeyError as -1
or:
val = name.strip()[4:].upper() except KeyError # Implicit `as None`
I would *not* add any spelling for an explicit bare-except equivalent. You would have to write:
val = name.strip()[4:].upper() except Exception as -1
Cheers, -Barry
I really like this one. It's way more general. I can see a use for IndexError as well (lists don't have the dict.get() method).
Also I would prefer not to use "as" this way. In the context of an exception, "as" already binds the exception to a variable so it's confusing.
What about:
val = name.strip()[4:].upper() except Exception: -1
That happens to be the exact syntax recommended by PEP 463 (modulo some distinguishing parentheses). https://www.python.org/dev/peps/pep-0463/ ChrisA
And I'll never approve syntax to make it easier to just ignore all
exceptions without looking at them.
On Tue, Dec 12, 2017 at 12:48 AM, Chris Angelico
On Tue, Dec 12, 2017 at 7:39 PM, Michel Desmoulin
wrote: Le 29/11/2017 à 19:02, Barry Warsaw a écrit :
On Nov 29, 2017, at 12:40, David Mertz
wrote: I think some syntax could be possible to only "catch" some exceptions
and let others propagate. Maybe:
val = name.strip()[4:].upper() except (AttributeError, KeyError): -1
I don't really like throwing a colon in an expression though. Perhaps
some other word or symbol could work instead. How does this read:
val = name.strip()[4:].upper() except -1 in (AttributeError,
KeyError)
I don’t know whether I like any of this <wink> but I think a more natural spelling would be:
val = name.strip()[4:].upper() except (AttributeError, KeyError) as -1
which could devolve into:
val = name.strip()[4:].upper() except KeyError as -1
or:
val = name.strip()[4:].upper() except KeyError # Implicit `as None`
I would *not* add any spelling for an explicit bare-except equivalent. You would have to write:
val = name.strip()[4:].upper() except Exception as -1
Cheers, -Barry
I really like this one. It's way more general. I can see a use for IndexError as well (lists don't have the dict.get() method).
Also I would prefer not to use "as" this way. In the context of an exception, "as" already binds the exception to a variable so it's confusing.
What about:
val = name.strip()[4:].upper() except Exception: -1
That happens to be the exact syntax recommended by PEP 463 (modulo some distinguishing parentheses).
https://www.python.org/dev/peps/pep-0463/
ChrisA _______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/ guido%40python.org
-- --Guido van Rossum (python.org/~guido)
On Wed, Dec 13, 2017 at 6:03 AM, Guido van Rossum
And I'll never approve syntax to make it easier to just ignore all exceptions without looking at them.
Well, I certainly wouldn't advocate "except Exception: -1", but the syntax is the same as "except KeyError: -1" which is less unreasonable. But PEP 463 was rejected, which means that any proposals along these lines need to first deal with the objections to that PEP, else there's not a lot of point discussing them. ChrisA
On Tue, 28 Nov 2017 12:10:54 -0800
Lukasz Langa
Hi Mark, it looks like the PEP is dormant for over two years now. I had multiple people ask me over the past few days about it though, so I wanted to ask if this is moving forward.
I am -1 on this PEP. I also think we don't need any additional syntax for the feature, regardless of how it's spelt exactly (or whether it's spelled rather than spelt). Regards Antoine.
participants (25)
-
Andrea Griffini
-
Antoine Pitrou
-
Barry Warsaw
-
Chris Angelico
-
Christian Heimes
-
David Mertz
-
Eric Fahlgren
-
Eric V. Smith
-
Ethan Furman
-
Greg Ewing
-
Guido van Rossum
-
Joao S. O. Bueno
-
Lukasz Langa
-
Mariatta Wijaya
-
Mark Haase
-
Michel Desmoulin
-
MRAB
-
Nick Coghlan
-
Paul Moore
-
Random832
-
Raymond Hettinger
-
Serhiy Storchaka
-
Steve Holden
-
Steven D'Aprano
-
Tres Seaver