<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Mon, Sep 28, 2015 at 12:47 PM, Andrew Barnert <span dir="ltr"><<a href="mailto:abarnert@yahoo.com" target="_blank">abarnert@yahoo.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">On Monday, September 28, 2015 12:05 PM, Guido van Rossum <<a href="mailto:guido@python.org">guido@python.org</a>> wrote:<br>
>On Mon, Sep 28, 2015 at 10:38 AM, Carl Meyer <<a href="mailto:carl@oddbird.net">carl@oddbird.net</a>> wrote:<br>
</span><span class="">>>"Propagating" refers to the proposed behavior where use of ?. or ?[<br>
>>"propagates" through the following chain of operations. For example:<br>
>><br>
>> x = foo?.bar.spam.eggs<br>
>><br>
>>Where both `.spam` and `.eggs` would behave like `?.spam` and `?.eggs`<br>
>>(propagating None rather than raising AttributeError), simply because a<br>
>>`.?` had occurred earlier in the chain. So the above behaves differently<br>
>>from:<br>
>><br>
>> temp = foo?.bar<br>
>> x = temp.spam.eggs<br>
>><br>
>>Which raises questions about whether the propagation escapes<br>
>>parentheses, too:<br>
>><br>
>> x = (foo?.bar).spam.eggs<br>
>><br>
><br>
>Oh, I see. That's evil.<br>
><br>
>The correct behavior here is that "foo?.bar.spam.eggs" should mean the same as<br>
><br>
> (None if foo is None else foo.bar.spam.eggs)<br>
><br>
>(Stop until you understand that is *not* the same as either of the alternatives you describe.)<br>
><br>
>I can see the confusion that led to the idea of "propagation" -- it probably comes from an attempt to define "foo?.bar" without reference to the context (in this case the relevant context is that it's followed by ".spam.eggs").<br>
<br>
<br>
</span>It would really help to have a complete spec, or at least a quick workthrough of how an expression gets parsed and compiled.<br></blockquote><div><br></div><div>Isn't the PEP author still planning to do that? But it hasn't happened yet. :-(<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
I assume it's something like this:<br>
<br>
spam?.eggs.cheese becomes this pseudo-AST (I've skipped the loads and maybe some other stuff):<br>
<br>
Expr(<br>
value=Attribute(<br>
value=Attribute(<br>
value=Name(id='spam'), attr='eggs', uptalk=True),<br>
attr='cheese', uptalk=False))<br></blockquote><div> <br></div><div>Hm, I think the problem is that this way of representing the tree encourages thinking that each attribute (with or without ?) can be treated on its own.<br></div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
… which is then compiled as this pseudo-bytecode:<br>
<br>
LOAD_NAME 'spam'<br>
DUP_TOP<br>
POP_JUMP_IF_NONE :label<br>
LOAD_ATTR 'eggs'<br>
LOAD_ATTR 'cheese'<br>
:label<br>
<br>
<br>
I've invented a new opcode POP_JUMP_IF_NONE, but it should be clear what it does. I think it's clear how replacing spam with any other expression works, and how subscripting works. So the only question is whether understanding how .eggs.cheese becomes a pair of LOAD_ATTRs is sufficient to understand how ?.eggs.cheese becomes a JUMP_IF_NONE followed by the same pair of LOAD_ATTRs through the same two steps.<br></blockquote><div><br></div><div>To most people of course that's indecipherable mumbo-jumbo. :-)<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
I suppose the reference documentation wording is also important here, to explain that an uptalked attributeref or subscription short-circuits the whole primary.<br>
</blockquote></div><br></div><div class="gmail_extra">Apparently clarifying that is the entire point of this thread. :-)<br clear="all"></div><div class="gmail_extra"><br>-- <br><div class="gmail_signature">--Guido van Rossum (<a href="http://python.org/~guido" target="_blank">python.org/~guido</a>)</div>
</div></div>