Re: [Python-ideas] PEP 505: None-aware operators

2018-08-01 Thread Chris Angelico
On Thu, Aug 2, 2018 at 12:04 AM, Jonathan Fine  wrote:
> Hi Steve
>
> Thank you for your reply.
>
> We're discussing the abstract to PEP 505, which writes
>  ===
> The "None-aware attribute access" operator ?. ("maybe dot") evaluates
> the complete expression if the left hand side evaluates to a value
> that is not None
> ===
>
> I gave (42).str as an example. I wrote
>
>> I don't see how to apply the prose in the abstract to this last
>> example. The left hand side is not None, so we "evaluate the complete
>> expression". On one reading, this is a recursion.
>
> You wrote
>> The phrasing could be clearer.
>
> I think the phrasing could be considerably improved (see below).
>
>> Since 42 is not None, it evaluates (42).str
>> [...]
>
> Based on this hint, here's what I think is a better statement.
> ===
> Let `lhs` be the value of the left hand side, and RHS the code
> fragment on the right hand side. If `lhs` is None, then the whole
> expression is `None`. Otherwise, `lhs . RHS` gives the value of the
> whole expression.
> ===
>
> Please would the experts tell me: Is it true? And if true, is it
> better? And can it be improved?

It may be true, but it isn't better IMO - especially not for the
abstract. It's unnecessarily pedantic. The current wording isn't
ambiguous, because infinite recursion makes no sense.

MAYBE change it to "evaluate the rest of the expression", but I don't
see a problem with the current wording.

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 505: None-aware operators

2018-08-01 Thread Jonathan Fine
Hi Steve

Thank you for your reply.

We're discussing the abstract to PEP 505, which writes
 ===
The "None-aware attribute access" operator ?. ("maybe dot") evaluates
the complete expression if the left hand side evaluates to a value
that is not None
===

I gave (42).str as an example. I wrote

> I don't see how to apply the prose in the abstract to this last
> example. The left hand side is not None, so we "evaluate the complete
> expression". On one reading, this is a recursion.

You wrote
> The phrasing could be clearer.

I think the phrasing could be considerably improved (see below).

> Since 42 is not None, it evaluates (42).str
> [...]

Based on this hint, here's what I think is a better statement.
===
Let `lhs` be the value of the left hand side, and RHS the code
fragment on the right hand side. If `lhs` is None, then the whole
expression is `None`. Otherwise, `lhs . RHS` gives the value of the
whole expression.
===

Please would the experts tell me: Is it true? And if true, is it
better? And can it be improved?

-- 
Jonathan
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 505: None-aware operators

2018-08-01 Thread Steven D'Aprano
On Wed, Aug 01, 2018 at 11:03:05AM +0100, Jonathan Fine wrote:

[...]
> After my last post, you wrote
> > None.?__str__
> > produces None, even though None has a __str__ attribute.
> 
> This surprises me. But I think it follows from the rules in
> https://www.python.org/dev/peps/pep-0505/#the-maybe-dot-and-maybe-subscript-operators

Correct. None?.__str__ is equivalent to:

_v = None
if _v is not None:
_v = _v.__str__
return _v

(except no actual _v variable is created, and it is not literally a 
return statement).


> My initial reading of
> >>> a ?. b
> was that if 'a' didn't have a 'b' attribute, then the result was None,
> whatever the string 'b'.
> 
> In other words, the same as
> >> getattr(a, name, None)

No. PEP 505 is for None-aware operators. It spends considerable time 
explaining that it treats None as special. It does not catch 
AttributeError from missing attributes.

(45)?.upper()

will fail with AttributeError, same as (45).upper() does.



> The abstract to PEP 505 writes
> ===
> The "None-aware attribute access" operator ?. ("maybe dot") evaluates
> the complete expression if the left hand side evaluates to a value
> that is not None
> ===
> 
> This is, of course, informal prose. I'm now reading it carefully.
> Here's a specific example.
> 
> >>> (42).__str__
> 
> >>> (42).str
> Traceback (most recent call last):
> AttributeError: 'int' object has no attribute 'str'
> >>> (42) ?. str
> 
> I don't see how to apply the prose in the abstract to this last
> example. The left hand side is not None, so we "evaluate the complete
> expression". On one reading, this is a recursion.

The phrasing could be clearer.

Since 42 is not None, it evaluates (42).str which of course will 
fail with AttributeError. To be specific, it is equivalent to something 
like this pseudo-code:

_v = 42
if _v is not None:
_v = _v.str
return _v

(The same disclaimer about _v and return apply as earlier.)




-- 
Steve
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 505: None-aware operators

2018-08-01 Thread Jonathan Fine
Hi Stephan

You wrote

> Let me stand up and claim that if a chain consists *only* of None-coalescing
> operations, then breaking up the chain by adding parentheses does not
> matter, ever.

You missed a post I made, 17 minutes before yours. I then believed
that PEP 505 specified.

#1. (None ?. dne) is None
#2. (None ?. dne ?. __str__) is None
#3. (None.__str__) is not None
#4. ((None ?. dne) ?. __str__) is (None.__str__)

After my last post, you wrote
> None.?__str__
> produces None, even though None has a __str__ attribute.

This surprises me. But I think it follows from the rules in
https://www.python.org/dev/peps/pep-0505/#the-maybe-dot-and-maybe-subscript-operators

My initial reading of
>>> a ?. b
was that if 'a' didn't have a 'b' attribute, then the result was None,
whatever the string 'b'.

In other words, the same as
>> getattr(a, name, None)

But you and I agree, I think, that PEP 505 specifies (in the cited
page fragment)
>>> a ?. anything
is always None, whenever 'a' is None, and for any non-keyword
identifier instead of 'anything'. Thank you for contributing this
clarification.

The abstract to PEP 505 writes
===
The "None-aware attribute access" operator ?. ("maybe dot") evaluates
the complete expression if the left hand side evaluates to a value
that is not None
===

This is, of course, informal prose. I'm now reading it carefully.
Here's a specific example.

>>> (42).__str__

>>> (42).str
Traceback (most recent call last):
AttributeError: 'int' object has no attribute 'str'
>>> (42) ?. str

I don't see how to apply the prose in the abstract to this last
example. The left hand side is not None, so we "evaluate the complete
expression". On one reading, this is a recursion.

I'd very much appreciate some help here.

-- 
Jonathan
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 505: None-aware operators

2018-08-01 Thread Chris Angelico
On Wed, Aug 1, 2018 at 7:09 PM, Jonathan Fine  wrote:
> Hi Chris
>
> We're discussing.
>> 10) a ?. b ?. c
>> 11) (a ?. b) ?. c
>
> I asked
>> So, are there any values of 'a' for which #10 and #11 don't give the
>> same result?
>
> You replied
>> I'm not prepared to put my neck out and say "They are absolutely
>> identical" and have people jump on me with some technicality. What is
>> your point here?
>
> I am willing to put my neck out and say a.b.c and (a.b).c are
> equivalent. And my understanding for PEP 505 is that #10 and #11 is
> that they are equivalent.

The first pair are easily proven, since we can just probe existing code.

>>> import dis
>>> dis.dis(lambda a: a.b.c)
  1   0 LOAD_FAST0 (a)
  2 LOAD_ATTR0 (b)
  4 LOAD_ATTR1 (c)
  6 RETURN_VALUE
>>> dis.dis(lambda a: (a.b).c)
  1   0 LOAD_FAST0 (a)
  2 LOAD_ATTR0 (b)
  4 LOAD_ATTR1 (c)
  6 RETURN_VALUE
>>>

Same byte code? Same result. Unless there's a bug in the peephole
optimizer or something, which I doubt.

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 505: None-aware operators

2018-08-01 Thread Stephan Houben
Op wo 1 aug. 2018 11:10 schreef Jonathan Fine :

>
>
> You're right to be cautious. My understanding of PEP 505 is that
> #13.  a ?. b ?. __str__
> #14. (a ?. b) ?. __str__
> are not equivalent. The first is None, and the other is None.__str__.
> That looks like a gotcha.
>


No.
None.?__str__
produces None, even though None has a __str__ attribute.

I am pretty sure
a?.b?.c == (a?.b)?.c

and more generically

chain_A ?. chain_B == (chain_A) ?. chain_B

Stephan


> (By the way, it was not my intention to catch you out. I'm simply
> looking for clarity. I wasn't aware of the gotcha until I started
> answering myself the question I had asked you.)
>
> However, the None object is somewhat special, in that all it's methods
> and double-under (dunder) methods. And one of them is __bool__.  And
> we can't add or change the attributes of None.
>
> Chris, you don't have to reply to this. But I would be pleased if an
> expert could either tell me that my neck is safe, or produce a value
> of 'a' that cuts it off (so to speak).
>
> --
> Jonathan
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 505: None-aware operators

2018-08-01 Thread Stephan Houben
Op wo 1 aug. 2018 10:50 schreef Chris Angelico :

> On Wed, Aug 1, 2018 at 6:45 PM, Jonathan Fine  wrote:
> > Hi Chris
> >
> > Thank you for your reply. I think we're making good progress.
> >
> > You wrote
> >
> >>> 10) a ?. b ?. c
> >>> 11) (a ?. b) ?. c
> >>
> >> I would parse those differently, but you may be right that they'll
> >> always have the same final result.
> >
> > I'd like to get some certainty on this. I'm not aware of any value of
> > 'a' for which #10 and #11 give different values. Can you (or anyone
> > else) think of any such value?
> >
> >> Technically they should result in different code, though.
> >
> > Maybe. We need to think. Should can be a difficult word. Elsewhere you
> > have, as I recall, pointed out that
> > if None:
> > do_something()
> > generates no code.
> >
> > Perhaps the compiler should collapse #11 to #10, if they are
> > equivalent. But this is a side issue.
> >
> > So, are there any values of 'a' for which #10 and #11 don't give the
> > same result?
>
> I'm not prepared to put my neck out and say "They are absolutely
> identical" and have people jump on me with some technicality.


Let me stand up and claim that if a chain consists *only* of
None-coalescing operations, then breaking up the chain by adding
parentheses does not matter, ever.

 So a?.b?.c is equivalent to (a?.b)?.c


What is
> your point here?
>

It is useful to establish rules under which a chain can be factored.

Stephan




> ChrisA
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 505: None-aware operators

2018-08-01 Thread Jonathan Fine
Hi Chris

We're discussing.
> 10) a ?. b ?. c
> 11) (a ?. b) ?. c

I asked
> So, are there any values of 'a' for which #10 and #11 don't give the
> same result?

You replied
> I'm not prepared to put my neck out and say "They are absolutely
> identical" and have people jump on me with some technicality. What is
> your point here?

I am willing to put my neck out and say a.b.c and (a.b).c are
equivalent. And my understanding for PEP 505 is that #10 and #11 is
that they are equivalent.

You're right to be cautious. My understanding of PEP 505 is that
#13.  a ?. b ?. __str__
#14. (a ?. b) ?. __str__
are not equivalent. The first is None, and the other is None.__str__.
That looks like a gotcha.

(By the way, it was not my intention to catch you out. I'm simply
looking for clarity. I wasn't aware of the gotcha until I started
answering myself the question I had asked you.)

However, the None object is somewhat special, in that all it's methods
and double-under (dunder) methods. And one of them is __bool__.  And
we can't add or change the attributes of None.

Chris, you don't have to reply to this. But I would be pleased if an
expert could either tell me that my neck is safe, or produce a value
of 'a' that cuts it off (so to speak).

-- 
Jonathan
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 505: None-aware operators

2018-08-01 Thread Chris Angelico
On Wed, Aug 1, 2018 at 6:45 PM, Jonathan Fine  wrote:
> Hi Chris
>
> Thank you for your reply. I think we're making good progress.
>
> You wrote
>
>>> 10) a ?. b ?. c
>>> 11) (a ?. b) ?. c
>>
>> I would parse those differently, but you may be right that they'll
>> always have the same final result.
>
> I'd like to get some certainty on this. I'm not aware of any value of
> 'a' for which #10 and #11 give different values. Can you (or anyone
> else) think of any such value?
>
>> Technically they should result in different code, though.
>
> Maybe. We need to think. Should can be a difficult word. Elsewhere you
> have, as I recall, pointed out that
> if None:
> do_something()
> generates no code.
>
> Perhaps the compiler should collapse #11 to #10, if they are
> equivalent. But this is a side issue.
>
> So, are there any values of 'a' for which #10 and #11 don't give the
> same result?

I'm not prepared to put my neck out and say "They are absolutely
identical" and have people jump on me with some technicality. What is
your point here?

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 505: None-aware operators

2018-08-01 Thread Jonathan Fine
Hi Chris

Thank you for your reply. I think we're making good progress.

You wrote

>> 10) a ?. b ?. c
>> 11) (a ?. b) ?. c
>
> I would parse those differently, but you may be right that they'll
> always have the same final result.

I'd like to get some certainty on this. I'm not aware of any value of
'a' for which #10 and #11 give different values. Can you (or anyone
else) think of any such value?

> Technically they should result in different code, though.

Maybe. We need to think. Should can be a difficult word. Elsewhere you
have, as I recall, pointed out that
if None:
do_something()
generates no code.

Perhaps the compiler should collapse #11 to #10, if they are
equivalent. But this is a side issue.

So, are there any values of 'a' for which #10 and #11 don't give the
same result?

-- 
Jonathan
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 505: None-aware operators

2018-08-01 Thread Chris Angelico
On Wed, Aug 1, 2018 at 6:00 PM, Jonathan Fine  wrote:
> Hi Chris
>
> You wrote:
>
>> Oh. The equivalent ones are #1 and #2, and #7 and #8, where this
>> proposal doesn't change anything. Otherwise, they're not equivalent.
>
> Are you sure. I'd also expect #10 and #11 to be equivalent.
>
> By the way, there's a typo in my examples: 11) (a .? b) ?. c

Hmm.

> 10) a ?. b ?. c
> 11) (a ?. b) ?. c

I would parse those differently, but you may be right that they'll
always have the same final result. Technically they should result in
different code, though.

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 505: None-aware operators

2018-08-01 Thread Jonathan Fine
Hi Chris

You wrote:

> Oh. The equivalent ones are #1 and #2, and #7 and #8, where this
> proposal doesn't change anything. Otherwise, they're not equivalent.

Are you sure. I'd also expect #10 and #11 to be equivalent.

By the way, there's a typo in my examples: 11) (a .? b) ?. c

-- 
Jonathan
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 505: None-aware operators

2018-08-01 Thread Jonathan Fine
Hi Chris

Thank you for your prompt reply. You wrote

> Incorrect. The short-circuiting behaviour ends at any sort of
> grouping. It's like how "a < b < c" is not equivalent to "(a < b) <
> c", nor to "a < (b < c)".

You've told me that my answer B is wrong. But you've not provided your
correct answer. I'd be most grateful if you could tell me what are the
equivalences between the 12 expressions I provided.

-- 
Jonathan
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 505: None-aware operators

2018-08-01 Thread Chris Angelico
On Wed, Aug 1, 2018 at 5:29 PM, Jonathan Fine  wrote:
> Hi All
>
> I have two further questions. I'm keen to clarify what is the
> behaviour specified by PEP 505. I'm not, at this time, interested in
> why and how PEP 505 specifies behaviour. I just wish, through explicit
> examples, to clarify the behaviour that is specified.
>
> Here 'a' is an identifier. Consider the following 12 expressions (I
> use the word loosely).
>
> 1) a . b . c
> 2) (a . b) . c
> 3) a . (b . c)
>
> 4) a ?. b . c
> 5) (a ?. b) . c
> 6) a ?. (b . c)
>
> 7) a . b ?. c
> 8) (a . b) ?. c
> 9) a . (b ?. c)
>
> 10) a ?. b ?. c
> 11) (a .? b) ?. c
> 12) a ?. (b ?. c)
>
> Question A: Which of the expressions are NOT valid (Python + PEP 505) syntax?
> Question B: Which of the valid (Python + PEP 505) expressions are
> equivalent, for all possible values of 'a'.
>
> The answer depends, of course, on the exact text of PEP 505. I've not
> read PEP 505 that closely. My expectations, based on my Python
> experience, are that PEP 505 would be written so that:
>
> Answer A: Expressions 3, 6, 9 and 12 are invalid. The others are valid.

Correct. After a dot (whether ?. or plain . ), you need a NAME, not
any form of expression (test, expr, etc).

> Answer B: 1 and 2 are equivalent. Similarly 4 and 5. Similarly 7 and
> 8. Similarly 10 and 11. There are no other equivalences (for all
> values of 'a').

Incorrect. The short-circuiting behaviour ends at any sort of
grouping. It's like how "a < b < c" is not equivalent to "(a < b) <
c", nor to "a < (b < c)".

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 505: None-aware operators

2018-08-01 Thread Jonathan Fine
Hi All

I have two further questions. I'm keen to clarify what is the
behaviour specified by PEP 505. I'm not, at this time, interested in
why and how PEP 505 specifies behaviour. I just wish, through explicit
examples, to clarify the behaviour that is specified.

Here 'a' is an identifier. Consider the following 12 expressions (I
use the word loosely).

1) a . b . c
2) (a . b) . c
3) a . (b . c)

4) a ?. b . c
5) (a ?. b) . c
6) a ?. (b . c)

7) a . b ?. c
8) (a . b) ?. c
9) a . (b ?. c)

10) a ?. b ?. c
11) (a .? b) ?. c
12) a ?. (b ?. c)

Question A: Which of the expressions are NOT valid (Python + PEP 505) syntax?
Question B: Which of the valid (Python + PEP 505) expressions are
equivalent, for all possible values of 'a'.

The answer depends, of course, on the exact text of PEP 505. I've not
read PEP 505 that closely. My expectations, based on my Python
experience, are that PEP 505 would be written so that:

Answer A: Expressions 3, 6, 9 and 12 are invalid. The others are valid.
Answer B: 1 and 2 are equivalent. Similarly 4 and 5. Similarly 7 and
8. Similarly 10 and 11. There are no other equivalences (for all
values of 'a').

I would like to know if my answers to my questions are correct, and if
not please may I be given correct answers. Thank you in advance.

-- 
Jonathan
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/