Re: [Python-ideas] PEP 505: None-aware operators: operators ?= and ?? and OR

Hi
There is a formatted version of this PEP at https://www.python.org/dev/peps/pep-0505/
I've taken a look at this, and have some comments on the first two examples drawn from standard library code. (And a very grateful +10 for writing a script to find such examples.) I've started a subthread, just to discuss the ?= and ?? operators. And something newish, that I call OR. FIRST EXAMPLE The first example is ---
Here, None is a sentinel value. The simpler code --- hi = hi or len(a) --- fails when hi is zero (or any other value that is False in the boolean context). This can be fixed by introducing a new operator OR which is similar to 'or' but has the semantics this example requires. Thus, given OR we can write --- hi = hi OR len(a) --- where (A OR B) returns A if A is not None, otherwise it returns B. (Recall that (A or B) returns A if bool(A), otherwise it returns B.) SECOND EXAMPLE The second example is ---
Once we have OR we would write this as --- encoding = encoding OR sys.getdefaultencoding() optdict = dict(encoding=encoding, css=options.css) --- And from here we can condense into a single (longish) line: --- optdict = dict(encoding=encoding OR sys.getdefaultencoding(), css=options.css) -- SUMMARY Here, for reference, are the suggestions using ?= and ?? in PEP 505. --- hi ??= len(a) --- optdict = dict(encoding=encoding ?? sys.getdefaultencoding(), css=options.css) --- Comments ?? suggestions. For example, would a None-aware AND operator be useful? -- Jonathan

On 19 July 2018 at 13:30, Jonathan Fine <jfine2358@gmail.com> wrote:
How does (A OR B) differ from the PEP's (A ?? B)? I don't particularly like it in either form. But ?? at least has the advantage of being used in other languages. [...]
Comments ?? suggestions. For example, would a None-aware AND operator be useful?
I see no value in a None-aware AND. Real use cases are the only reasonable argument for such a thing, not arguments based on symmetry (or generalisation). And I doubt I'd find real-world use cases particularly compelling. Paul

I've started a subthread, just to discuss the ?= and ?? operators. And something newish, that I call OR.
I would think `||` would be much better. It could be a kind of "semantic or" which could use the aforementioned dunder has_value. -1, though, but to the general None-awareness. Pål

Hello. Even if I'm -1 on the general idea of a None-aware, for a lot of reason already mentionned in this thread, the syntax "??" proposed (that I find much less readable than the current version) is still better IMHO. How many programmer will read "||" or "OR" as a classic "or" operator? Programmers needs to learn the language, but making it easy for them to understand and learn is important in python. More than that, if you use "||" or "OR" thinking you use "or", nothing will help you to understand what isn't working in your code. So -1 on that idea even if PEP 505 were accepted. Nathan Mugnier
Message du 19/07/18 15:06 De : "Pål Grønås Drange"
A : "Jonathan Fine" Copie à : "Python-Ideas"
_______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/

Operators that only vary by case would be... confusing. I'm not super keen on the other syntax (either the ?? or .? operators) but I do think they read well in C# where they come from. Different things work in different languages, some times. What about a new keyword: default So you'd write the above examples like this: default hi = len(a) # Only executes the assignment if the left-hand is None default encoding = sys.getdefaultencoding() On Thu, Jul 19, 2018 at 9:06 AM, Pål Grønås Drange <paal.drange@gmail.com> wrote:

If we're about to use a new keyword, it could be infix too: a = b ifnone c Although the assignment version looks unusual: b ifnone= c Then with the "default b = c" would look like this: ifnone b = c Le jeu. 19 juil. 2018 à 15:30, Calvin Spealman <cspealma@redhat.com> a écrit :

The concatenated name reads a little weird. Alternatively, extend the conditional expression syntax. a = b if None c equivalent to a = b if b is None else c On Thu, Jul 19, 2018 at 9:35 AM, Robert Vanden Eynde <robertve92@gmail.com> wrote:

Calvin Spealman wrote:
Operators that only vary by case would be... confusing.
Also I'd prefer to see AND and OR (or maybe And and Or) reserved for possible use as overridable, non-short-circuiting forms of "and" and "or" for use by DSLs. -- Greg

On 7/19/2018 8:30 AM, Jonathan Fine wrote:
Antoine Pitrou proposed the same thing, using the existing 'else' as the spelling. 'hi else len(s)' abbreviates the existing 'hi if hi is not None else len(s)'. with the boilerplate 'if x is not None' removed.
To make the parallel more obvious, (A or B) also abbreviates tem = A; tem if bool(tem) is not False else B -- Terry Jan Reedy

Hi I'm new to that list, hope, that my idea will be helpfull. hi = hi OR len(a)
--- where (A OR B) returns A if A is not None, otherwise it returns B.
Probably, we can introduce syntactic sugar for "if not equal" comparison? Not only for "is not None" check, but for comparison with any expression. Something like: x = foo if 'value': bar equal to : x = foo if foo != 'value' else bar so, expression: x = foo if foo is not None else bar become: x = foo if None: bar That syntax does not use new keywords or operators, looks pythonic and simplify most common "is not None" expression. -- Regards, Aliaksei Yaletski. Homepage: http://tiendil.org Skype: Tiendil

Proposal a __very__ dumbed down "try" expression ==================================================== variable = try Expression as not sentinel [else default] The semantic is: 1 - try the expression. If any call (from a normal method, or a __dunder__ one) returns the sentinel, we shortcircuit. 2 - if we shortcircuit, the variable will be set do the default value. If no default is provided, the variable is set to the sentinel. 3 - if we don't shortcircuit, the returned value is the one from the expression. Example ========== value = try foo.bar[0] as not None If anything returns None, we shortcircuit and value will end up being None. Otherwise value contains the result of foo.bar[0]. value = try foo.bar[0] as not True If anything returns True, we shortcircuit and value will end being True. Otherwise value contains the result of foo.bar[0]. value = try foo.bar[0] as not None else "foo" If anything returns None, we shortcircuit and value will end up being 'foo'. Otherwise value contains the result of foo.bar[0]. value = try foo.bar[0] as not True else "foo" If anything returns True, we shortcircuit and value will end up being 'foo'. Otherwise value contains the result of foo.bar[0]. This as several benefits: ========================= - Does not introduce new keywords or operators - Read pretty much as ordinary Python - Allow for inline try, as suggested before several times on python-idea, but restrict it to a very narrow subset of what it can do. This will end the debate about inline try/except, while sill providing a sane subsets of use cases it would have provided. - more flexible than ? as it allows to choose what to choose the sentinel and the default value instead of just None. - the expression is untouched. It's surrounded by the rest, so it still reads as the expression would without try / as. - avoding "except", exception names and ":" make sure we don't confuse this try expression with the regular try/except statements. try would then be a very restricted version of it, like lambda is for def. If you don't like these keywords =============================== We can opt for something different: value = try Expression as not sentinel [or default] value = try Expression if not sentinel [else default] value = try Expression with not sentinel [else default] The proposal is more about the structure try (stuff), guard against a sentinel, and optionally return a default value. Besides, I don't know what the grammar would allow.

I like it much better than the operator version, if I understand correctly, it's like a watcher for special value, that monitor the stack. Danger is that it monitor the whole stack, so that final result is dependent on how much you decompose your algorithm into nested fiction calls: all return values will be monitored, and only return values... But if you refactor a big function into nested functions, and happen to return the special value in the new subfunctions, it will have side effects, that can not be known within the context: it expose internals that used to be hidden, deliberately so...

On 20/07/18 14:06, Michel Desmoulin wrote:
I like this approach. I think it should play nice with the ternary if, though I haven't actually checked the grammar. My only doubt is how much value there is to having a sentinel other than "None". -- Rhodri James *-* Kynesim Ltd

RE none-aware operators in general: +1 overall for the latest version of PEP 505 and the utility of ?? in particular. There are several places in my code that could be simplified with ??. find-pep505.py on my current Django-oriented codebase gives: Total None-coalescing `if` blocks: 43 Total [possible] None-coalescing `or`: 4 Total None-coalescing ternaries: 8 Total Safe navigation `and`: 0 Total Safe navigation `if` blocks: 6 Total Safe navigation ternaries: 17 RE OR and ||: * -1 for "OR" as an operator. Insufficiently distinct from "or". Reads the same out loud despite being a different operator. * -1 for "||" with none-aware semantics. This differs from the semantics in every C-derived language I can think of, which will be confusing to several other developers. David Foster | Seattle, WA, USA On 7/19/18 5:30 AM, Jonathan Fine wrote:

Reads the same out loud despite being a different operator.
How are `??`, `.?`, and the others pronounced? dhuh, dothuh? Or just read the expressions as if it were a question? -1 on 505, +1 on waiting a while with introducing new syntax Pål

mangle_from_ = True if policy is None else policy.mangle_from_
After updating:
mangle_from_ = policy?.mangle_from_ ?? True I cannot see how these are equivalent, and cannot understand what the cryptic comment means.
policy?.mangle_from_ ?? True True (??? since lhs is None?)

Hi Eric [Steve Dower: Eric seems to have found a bug in the PEP. Where to report?] You quoted, from PEP 505, Before
mangle_from_ = True if policy is None else policy.mangle_from_
After
mangle_from_ = policy?.mangle_from_ ?? True
You then remarked
I cannot see how these are equivalent
I don't see the equivalence either. If `policy.mangle_from_ is None` then surely Before gives None, while After gives True. Here's the process for filing bugs in a PEP https://www.python.org/dev/peps/pep-0001/#reporting-pep-bugs-or-submitting-p... As we seem to be in early draft stage, perhaps communicate first with PEP author (Steve Dower, copied). -- Jonathan

On 2018-08-02 20:03, Eric Fahlgren wrote:
If there's a policy, use policy.mangle_from_. If there's no policy, default to True. The comment is a reminder that you can't use 'or' instead of '??' because 'policy.mangle_from_' could be False and you don't want it to default to True in that case.
No, it's not 'policy.mangle_from_' that could be None, it's 'policy' that could be None (i.e. there's no policy).

On Thu, Aug 2, 2018 at 1:22 PM MRAB <python@mrabarnett.plus.com> wrote:
In my example, there is a policy, and the value of policy.mangle_from_ is set to None. Thus the above should be equivalent to this
None ?? True True
Unless, of course, I completely misunderstand the way the ?? operator works. This is not the same as the original code, they are not equivalent.

On Thu, Aug 2, 2018 at 3:39 PM MRAB <python@mrabarnett.plus.com> wrote:
In the relevant code, is policy.mangle_from_ ever None?
That's impossible to know, since the initializer where this code originally appears puts no constraints on the value of 'policy', it's just assumed to have a 'mangle_from_' member... I would be paranoid and assume, yes, it can take on a value of None as there's nothing to indicate that it can't. class Generator: ... def __init__(self, outfp, mangle_from_=None, maxheaderlen=None, *, policy=None): ... if mangle_from_ is None: mangle_from_ = True if policy is None else policy.mangle_from_ self._fp = outfp self._mangle_from_ = mangle_from_

On 2018-08-02 7:01 PM, Eric Fahlgren wrote:
I would make the opposite argument and claim that since when policy is None mangle_from_ is initialised to True and not None, None is likely not a potential value for policy.mangle_from_. Looking at Lib/email/_policybase.py where the abstract policy class in question is defined, policies default their mangle_from_ to False, which gives additional credence to the notion that policy.mangle_from_ is not meant to be None. So yes, *strictly speaking* the two chunks of code are not exactly the same. In practice, they'll act the same way given sensible inputs. Alex

Hi Alexandre Thank you for your post. In PEP 505 the context for the example being discussed is:
Some of these are shown below as examples before and after converting to use the new operators.
You wrote:
So yes, *strictly speaking* the two chunks of code are not exactly the same.
I see nothing in the context that indicates that given suitable (Python) context, the before and after expressions give different values. I assumed the before and after values were intended to be the same. By the way, I think that even without your *strictly speaking*, the two chunks of code are not exactly the same (in that they can give different values from identical inputs).
In practice, they'll act the same way given sensible inputs.
For me, the truth or falsity of this statement requires more than the peep-hole view of the code supplied by the PEP. Your argument for its truth certainly looked beyond the PEP. I think lack of clarity can mislead, and prevents the PEP performing properly one of its key functions === https://www.python.org/dev/peps/pep-0001/#what-is-a-pep The PEP should provide a concise technical specification of the feature and a rationale for the feature [being proposed]. === and so is a bug in the PEP. Fixing it will help the progress of the PEP. Where to report the bug? Either to Steve Dower, or raise an issue on github. https://www.python.org/dev/peps/pep-0001/#reporting-pep-bugs-or-submitting-p... Steve's already been emailed on this. We're waiting to hear back from him. -- Jonathan

On Thu, Aug 2, 2018 at 10:06 PM Alexandre Brault <abrault@mapgears.com> wrote:
After looking at the code a bit more, I agree, we've uncovered a bug in the stdlib and the null coalescing version actually fixes it. So yes, *strictly speaking* the two chunks of code are not exactly the
same. In practice, they'll act the same way given sensible inputs.
But! We are not here to talk about bugs in the email package, this discussion is about PEP 505, which means to me that the example is a bug in the PEP. In my view, the before and after examples should have identical results, unless there is some very clear and thorough discussion accompanying the example as to why they are different and more importantly, why the "after" version is better or worse. In this light, the example certainly needs a lot of work.

On Fri, Aug 03, 2018 at 06:30:25AM -0700, Eric Fahlgren wrote:
On the contrary! It strongly suggests to me that None-aware operators, or at least this one, makes it *easier* to write correct code than incorrect code. If your analysis that the email package is buggy is correct, this is a strong example in favour of the none-aware operator.
It needs some work. Something like "Here's an example in the standard library. On converting it to none-aware version, we realised the std lib version is buggy, because ...". A couple of sentences. -- Steve

On Thu, Aug 02, 2018 at 06:50:47PM +0200, Pål Grønås Drange wrote:
Reads the same out loud despite being a different operator.
How are `??`, `.?`, and the others pronounced?
Did you read the PEP? It answers that question. https://www.python.org/dev/peps/pep-0505/#reading-expressions I'm happy to read them as: spam ?? eggs spam maybe eggs spam or eggs if None spam?.eggs spam maybe-dot eggs spam dot eggs if not None etc depending on context. But I expect that some clever person will think up a nickname for it, like the Elvis operator: https://en.wikipedia.org/wiki/Elvis_operator -- Steve

On 19 July 2018 at 13:30, Jonathan Fine <jfine2358@gmail.com> wrote:
How does (A OR B) differ from the PEP's (A ?? B)? I don't particularly like it in either form. But ?? at least has the advantage of being used in other languages. [...]
Comments ?? suggestions. For example, would a None-aware AND operator be useful?
I see no value in a None-aware AND. Real use cases are the only reasonable argument for such a thing, not arguments based on symmetry (or generalisation). And I doubt I'd find real-world use cases particularly compelling. Paul

I've started a subthread, just to discuss the ?= and ?? operators. And something newish, that I call OR.
I would think `||` would be much better. It could be a kind of "semantic or" which could use the aforementioned dunder has_value. -1, though, but to the general None-awareness. Pål

Hello. Even if I'm -1 on the general idea of a None-aware, for a lot of reason already mentionned in this thread, the syntax "??" proposed (that I find much less readable than the current version) is still better IMHO. How many programmer will read "||" or "OR" as a classic "or" operator? Programmers needs to learn the language, but making it easy for them to understand and learn is important in python. More than that, if you use "||" or "OR" thinking you use "or", nothing will help you to understand what isn't working in your code. So -1 on that idea even if PEP 505 were accepted. Nathan Mugnier
Message du 19/07/18 15:06 De : "Pål Grønås Drange"
A : "Jonathan Fine" Copie à : "Python-Ideas"
_______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/

Operators that only vary by case would be... confusing. I'm not super keen on the other syntax (either the ?? or .? operators) but I do think they read well in C# where they come from. Different things work in different languages, some times. What about a new keyword: default So you'd write the above examples like this: default hi = len(a) # Only executes the assignment if the left-hand is None default encoding = sys.getdefaultencoding() On Thu, Jul 19, 2018 at 9:06 AM, Pål Grønås Drange <paal.drange@gmail.com> wrote:

If we're about to use a new keyword, it could be infix too: a = b ifnone c Although the assignment version looks unusual: b ifnone= c Then with the "default b = c" would look like this: ifnone b = c Le jeu. 19 juil. 2018 à 15:30, Calvin Spealman <cspealma@redhat.com> a écrit :

The concatenated name reads a little weird. Alternatively, extend the conditional expression syntax. a = b if None c equivalent to a = b if b is None else c On Thu, Jul 19, 2018 at 9:35 AM, Robert Vanden Eynde <robertve92@gmail.com> wrote:

Calvin Spealman wrote:
Operators that only vary by case would be... confusing.
Also I'd prefer to see AND and OR (or maybe And and Or) reserved for possible use as overridable, non-short-circuiting forms of "and" and "or" for use by DSLs. -- Greg

On 7/19/2018 8:30 AM, Jonathan Fine wrote:
Antoine Pitrou proposed the same thing, using the existing 'else' as the spelling. 'hi else len(s)' abbreviates the existing 'hi if hi is not None else len(s)'. with the boilerplate 'if x is not None' removed.
To make the parallel more obvious, (A or B) also abbreviates tem = A; tem if bool(tem) is not False else B -- Terry Jan Reedy

Hi I'm new to that list, hope, that my idea will be helpfull. hi = hi OR len(a)
--- where (A OR B) returns A if A is not None, otherwise it returns B.
Probably, we can introduce syntactic sugar for "if not equal" comparison? Not only for "is not None" check, but for comparison with any expression. Something like: x = foo if 'value': bar equal to : x = foo if foo != 'value' else bar so, expression: x = foo if foo is not None else bar become: x = foo if None: bar That syntax does not use new keywords or operators, looks pythonic and simplify most common "is not None" expression. -- Regards, Aliaksei Yaletski. Homepage: http://tiendil.org Skype: Tiendil

Proposal a __very__ dumbed down "try" expression ==================================================== variable = try Expression as not sentinel [else default] The semantic is: 1 - try the expression. If any call (from a normal method, or a __dunder__ one) returns the sentinel, we shortcircuit. 2 - if we shortcircuit, the variable will be set do the default value. If no default is provided, the variable is set to the sentinel. 3 - if we don't shortcircuit, the returned value is the one from the expression. Example ========== value = try foo.bar[0] as not None If anything returns None, we shortcircuit and value will end up being None. Otherwise value contains the result of foo.bar[0]. value = try foo.bar[0] as not True If anything returns True, we shortcircuit and value will end being True. Otherwise value contains the result of foo.bar[0]. value = try foo.bar[0] as not None else "foo" If anything returns None, we shortcircuit and value will end up being 'foo'. Otherwise value contains the result of foo.bar[0]. value = try foo.bar[0] as not True else "foo" If anything returns True, we shortcircuit and value will end up being 'foo'. Otherwise value contains the result of foo.bar[0]. This as several benefits: ========================= - Does not introduce new keywords or operators - Read pretty much as ordinary Python - Allow for inline try, as suggested before several times on python-idea, but restrict it to a very narrow subset of what it can do. This will end the debate about inline try/except, while sill providing a sane subsets of use cases it would have provided. - more flexible than ? as it allows to choose what to choose the sentinel and the default value instead of just None. - the expression is untouched. It's surrounded by the rest, so it still reads as the expression would without try / as. - avoding "except", exception names and ":" make sure we don't confuse this try expression with the regular try/except statements. try would then be a very restricted version of it, like lambda is for def. If you don't like these keywords =============================== We can opt for something different: value = try Expression as not sentinel [or default] value = try Expression if not sentinel [else default] value = try Expression with not sentinel [else default] The proposal is more about the structure try (stuff), guard against a sentinel, and optionally return a default value. Besides, I don't know what the grammar would allow.

I like it much better than the operator version, if I understand correctly, it's like a watcher for special value, that monitor the stack. Danger is that it monitor the whole stack, so that final result is dependent on how much you decompose your algorithm into nested fiction calls: all return values will be monitored, and only return values... But if you refactor a big function into nested functions, and happen to return the special value in the new subfunctions, it will have side effects, that can not be known within the context: it expose internals that used to be hidden, deliberately so...

On 20/07/18 14:06, Michel Desmoulin wrote:
I like this approach. I think it should play nice with the ternary if, though I haven't actually checked the grammar. My only doubt is how much value there is to having a sentinel other than "None". -- Rhodri James *-* Kynesim Ltd

RE none-aware operators in general: +1 overall for the latest version of PEP 505 and the utility of ?? in particular. There are several places in my code that could be simplified with ??. find-pep505.py on my current Django-oriented codebase gives: Total None-coalescing `if` blocks: 43 Total [possible] None-coalescing `or`: 4 Total None-coalescing ternaries: 8 Total Safe navigation `and`: 0 Total Safe navigation `if` blocks: 6 Total Safe navigation ternaries: 17 RE OR and ||: * -1 for "OR" as an operator. Insufficiently distinct from "or". Reads the same out loud despite being a different operator. * -1 for "||" with none-aware semantics. This differs from the semantics in every C-derived language I can think of, which will be confusing to several other developers. David Foster | Seattle, WA, USA On 7/19/18 5:30 AM, Jonathan Fine wrote:

Reads the same out loud despite being a different operator.
How are `??`, `.?`, and the others pronounced? dhuh, dothuh? Or just read the expressions as if it were a question? -1 on 505, +1 on waiting a while with introducing new syntax Pål

mangle_from_ = True if policy is None else policy.mangle_from_
After updating:
mangle_from_ = policy?.mangle_from_ ?? True I cannot see how these are equivalent, and cannot understand what the cryptic comment means.
policy?.mangle_from_ ?? True True (??? since lhs is None?)

Hi Eric [Steve Dower: Eric seems to have found a bug in the PEP. Where to report?] You quoted, from PEP 505, Before
mangle_from_ = True if policy is None else policy.mangle_from_
After
mangle_from_ = policy?.mangle_from_ ?? True
You then remarked
I cannot see how these are equivalent
I don't see the equivalence either. If `policy.mangle_from_ is None` then surely Before gives None, while After gives True. Here's the process for filing bugs in a PEP https://www.python.org/dev/peps/pep-0001/#reporting-pep-bugs-or-submitting-p... As we seem to be in early draft stage, perhaps communicate first with PEP author (Steve Dower, copied). -- Jonathan

On 2018-08-02 20:03, Eric Fahlgren wrote:
If there's a policy, use policy.mangle_from_. If there's no policy, default to True. The comment is a reminder that you can't use 'or' instead of '??' because 'policy.mangle_from_' could be False and you don't want it to default to True in that case.
No, it's not 'policy.mangle_from_' that could be None, it's 'policy' that could be None (i.e. there's no policy).

On Thu, Aug 2, 2018 at 1:22 PM MRAB <python@mrabarnett.plus.com> wrote:
In my example, there is a policy, and the value of policy.mangle_from_ is set to None. Thus the above should be equivalent to this
None ?? True True
Unless, of course, I completely misunderstand the way the ?? operator works. This is not the same as the original code, they are not equivalent.

On Thu, Aug 2, 2018 at 3:39 PM MRAB <python@mrabarnett.plus.com> wrote:
In the relevant code, is policy.mangle_from_ ever None?
That's impossible to know, since the initializer where this code originally appears puts no constraints on the value of 'policy', it's just assumed to have a 'mangle_from_' member... I would be paranoid and assume, yes, it can take on a value of None as there's nothing to indicate that it can't. class Generator: ... def __init__(self, outfp, mangle_from_=None, maxheaderlen=None, *, policy=None): ... if mangle_from_ is None: mangle_from_ = True if policy is None else policy.mangle_from_ self._fp = outfp self._mangle_from_ = mangle_from_

On 2018-08-02 7:01 PM, Eric Fahlgren wrote:
I would make the opposite argument and claim that since when policy is None mangle_from_ is initialised to True and not None, None is likely not a potential value for policy.mangle_from_. Looking at Lib/email/_policybase.py where the abstract policy class in question is defined, policies default their mangle_from_ to False, which gives additional credence to the notion that policy.mangle_from_ is not meant to be None. So yes, *strictly speaking* the two chunks of code are not exactly the same. In practice, they'll act the same way given sensible inputs. Alex

Hi Alexandre Thank you for your post. In PEP 505 the context for the example being discussed is:
Some of these are shown below as examples before and after converting to use the new operators.
You wrote:
So yes, *strictly speaking* the two chunks of code are not exactly the same.
I see nothing in the context that indicates that given suitable (Python) context, the before and after expressions give different values. I assumed the before and after values were intended to be the same. By the way, I think that even without your *strictly speaking*, the two chunks of code are not exactly the same (in that they can give different values from identical inputs).
In practice, they'll act the same way given sensible inputs.
For me, the truth or falsity of this statement requires more than the peep-hole view of the code supplied by the PEP. Your argument for its truth certainly looked beyond the PEP. I think lack of clarity can mislead, and prevents the PEP performing properly one of its key functions === https://www.python.org/dev/peps/pep-0001/#what-is-a-pep The PEP should provide a concise technical specification of the feature and a rationale for the feature [being proposed]. === and so is a bug in the PEP. Fixing it will help the progress of the PEP. Where to report the bug? Either to Steve Dower, or raise an issue on github. https://www.python.org/dev/peps/pep-0001/#reporting-pep-bugs-or-submitting-p... Steve's already been emailed on this. We're waiting to hear back from him. -- Jonathan

On Thu, Aug 2, 2018 at 10:06 PM Alexandre Brault <abrault@mapgears.com> wrote:
After looking at the code a bit more, I agree, we've uncovered a bug in the stdlib and the null coalescing version actually fixes it. So yes, *strictly speaking* the two chunks of code are not exactly the
same. In practice, they'll act the same way given sensible inputs.
But! We are not here to talk about bugs in the email package, this discussion is about PEP 505, which means to me that the example is a bug in the PEP. In my view, the before and after examples should have identical results, unless there is some very clear and thorough discussion accompanying the example as to why they are different and more importantly, why the "after" version is better or worse. In this light, the example certainly needs a lot of work.

On Fri, Aug 03, 2018 at 06:30:25AM -0700, Eric Fahlgren wrote:
On the contrary! It strongly suggests to me that None-aware operators, or at least this one, makes it *easier* to write correct code than incorrect code. If your analysis that the email package is buggy is correct, this is a strong example in favour of the none-aware operator.
It needs some work. Something like "Here's an example in the standard library. On converting it to none-aware version, we realised the std lib version is buggy, because ...". A couple of sentences. -- Steve

On Thu, Aug 02, 2018 at 06:50:47PM +0200, Pål Grønås Drange wrote:
Reads the same out loud despite being a different operator.
How are `??`, `.?`, and the others pronounced?
Did you read the PEP? It answers that question. https://www.python.org/dev/peps/pep-0505/#reading-expressions I'm happy to read them as: spam ?? eggs spam maybe eggs spam or eggs if None spam?.eggs spam maybe-dot eggs spam dot eggs if not None etc depending on context. But I expect that some clever person will think up a nickname for it, like the Elvis operator: https://en.wikipedia.org/wiki/Elvis_operator -- Steve
participants (17)
-
Alexandre Brault
-
Aliaksei Yaletski
-
Calvin Spealman
-
David Foster
-
Eric Fahlgren
-
Greg Ewing
-
Grégory Lielens
-
Jonathan Fine
-
Michel Desmoulin
-
MRAB
-
Nathan
-
Paul Moore
-
Pål Grønås Drange
-
Rhodri James
-
Robert Vanden Eynde
-
Steven D'Aprano
-
Terry Reedy