[Python-ideas] Dart-like method cascading operator in Python

Andrew Barnert abarnert at yahoo.com
Sat Nov 23 23:18:56 CET 2013


The biggest problem with most of the variants of this idea suggested so far is that they refer to things that don't exist--in particular, they treat the assignment statement, the assignment target, and/or the suite as something with a value. None of them have values, or could have values, without some radical change like a way to treat a suite of statements as an expression.

So, in the interests of having something to debate, here's an attempt at a concrete, implementable syntax and semantics without any of these problems that I think offers everything that people want that's actually possible:

    compound_expression_stmt ::= expression_list ":" suite

    compound_assignment_stmt ::= (target_list "=")+ (expression_list | yield_expression) ":" suite

The only difference to simple expression statements and assignment statements, as defined in 7.1 and 7.2, is that the suite is executed immediately after evaluating the expression list (or yield expression), before assignment of the value (of the expression list or yield expression, not some other value) to the target lists or writing of the repr to the interactive output.

    dot_attribute_ref ::= ".." identifier

A dot attribute reference in the suite of a compound expression or assignment statement is evaluated exactly like a simple attribute reference, as defined in 6.3.1 and in 7.2, except that the value of the expression list or yield expression is used as the value of the primary.

I believe a dot attribute reference outside of could raise a SyntaxError at parse time. If not, it raises a ValueError at runtime, because the dot-value of the current suite is None.

I believe this handles all of the examples given so far. It can be nested in the obvious way, without needing any new semantics. Assignment statements with expression lists of more than one expression are useless (you can't mutate a tuple), but not illegal. It could be extended to allow dot-subscripting and dot-slicing trivially, if those are desirable. And it's a very simple change to the syntax and semantics of the language, that doesn't have any radical undesirable consequences.

I still don't really like the idea, but it's nice to know that it is actually doable. I'm maybe -.5 instead of -1 if it doesn't require statements having values and magic guessing of which statements in a suite replace a value and which don't and so on.


>________________________________
> From: Perešíni Peter <ppershing at gmail.com>
>To: Bruce Leban <bruce at leapyear.org> 
>Cc: Python-Ideas <python-ideas at python.org> 
>Sent: Friday, November 22, 2013 1:32 AM
>Subject: Re: [Python-ideas] Dart-like method cascading operator in Python
> 
>
>
>
>
>
>
>
>On Fri, Nov 22, 2013 at 10:16 AM, Bruce Leban <bruce at leapyear.org> wrote:
>
>
>>Steven D'Aprano:
>>
>>>> Perhaps, but that's not relevant to the proposed syntax. The proposed
>>syntax has more to do with "then" rather than "there", that is, "the
>>last object used", not "the object at location 1234".
>>>> For starters, you should explain precisely how the compiler will determine what is the "last object used" in practice. Your examples so far suggest it is based on the last line of source code, but that's tricky.
>>Perešíni Peter:
>>
>>> I think the reasonable way to define it would be that the cascade operator will act only if the last thing (on the previous line) was an expression. In particular, all statements like "del y, for, while, if-else" followed by a cascade should be a parse error with the exception of the assignment which is a statement but we want to allow it. I am not sure about yield -- it can be a bit difficult to agree on the exact semantic there (e.g. should I yield first, then continue with the cascade or should I execute the whole cascade and yield as a final step?)
>>I don't think that's well-defined at all. Furthermore last object on *previous* line is less useful than object on line that introduces the suite. Consider:
>>obj::
>>    ..x = b
>>    # is last object b? That's not useful. obj.x? That may not be an object
>>    ..y = 3
>>    # even more clearly not useful
>>    ..sort()
>>    # this always returns None
>>In:
>><expression>::
>>    <lines all referencing that one expression via ..>
>Yes, exactly. As usual I did not write my thoughts clearly. By the last line I really meant "last object on the preceding line ending with :: having the smaller indent than the current line" 
>I know exactly what that does without reading each intervening line which could change the object being operated on. I can use this with objects that *don't* support chaining which is what makes it useful. I can reorder lines worrying only about method execution order not breaking chaining.
>>The traceback complaint is a red herring as it can easily inject the line that has the expression being operated on.
>>In summary I would only allow the first line to contain an expression or assignment which by definition has a single explicit value. That values is what all statements reference:
>>obj::
>>    ..x = 3
>>    ..y()  # operates on obj not obj.x or 3
>>    ..z(). # ditto
>>a[index] = foo(...) ::  # don't need to repeat a[index] below or use a temporary name
>>    ..x = 3
>>    ..y()
>>    ..z()
>> 
>>>I think the reasonable way to define it would be that the cascade operator will act only if the last thing (on the previous line) was an expression. In particular, all statements like "del y, for, while, if-else" followed by a cascade should be a parse error with the exception of the assignment which is a statement but we want to allow it. I am not sure about yield -- it can be a bit difficult to agree on the exact semantic there (e.g. should I yield first, then continue with the cascade or should I execute the whole cascade and yield as a final step?)
>>> 
>Actually, thinking about my own ideas -- the bigger problem than yield is the return. I am not sure if things like
>
>
>return list(range(10))
>    ..reverse()
>    ..pop(0)
>
>
>should be allowed or not - having something being executed after the return statement line might be a bit confusing
>_______________________________________________
>Python-ideas mailing list
>Python-ideas at python.org
>https://mail.python.org/mailman/listinfo/python-ideas
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20131123/ad53757f/attachment.html>


More information about the Python-ideas mailing list