[Python-ideas] If branch merging

Nick Coghlan ncoghlan at gmail.com
Mon Jun 8 05:41:01 CEST 2015


On 8 June 2015 at 12:45, Chris Angelico <rosuav at gmail.com> wrote:
> On Mon, Jun 8, 2015 at 12:33 PM, Stephen J. Turnbull <stephen at xemacs.org> wrote:
>> I'm definitely -1 on the also, alif syntax at this point.  On the
>> other hand, having done a lot of C programming in my misspent youth, I
>> do miss anaphoric conditionals, so I too would like to see the
>> possibility of "if cond as var: do_something_with_var" explored.  Of
>> course Nick is right that automatic common subexpression elimination
>> (CSE) is the big win, but manual CSE can improve readability.
>
> Part of the trouble with depending on CSE is that Python is so dynamic
> that you can't depend on things having no side effects... but the more
> important part, in my opinion, is that duplication is a source code
> maintenance problem.

Yes, this is the part of the problem definition I agree with, which is
why I think named subexpressions are the most attractive alternative
presented in the past discussions.

Our typical answer is "pull the named subexpression out to a separate
assignment statement and give it a name", but there are a range of
constructs where that poses a problem. For example:

    x = a.b if a.b else a.c

    while a.b:
        x = a.b

    [a.b for a in iterable if a.b]

Eliminating the duplication with named subexpressions would be
straightforward (I'd suggest making the parentheses mandatory for this
construct, which would also avoid ambiguity in the with statement and
exception handler clause cases):

    x = b if (a.b as b) else a.c

    while (a.b as x):
        ...

    [b for a in iterable if (a.b as b)]

By contrast, eliminating the duplication *today* requires switching to
very different structures based on the underlying patterns otherwise
hidden behind the syntactic sugar:

    x = a.b
    if not x:
        x = a.c

    while True:
        x = a.b
        if not x:
            break
        ...

    result = []
    for a in iterable:
        b = a.b
        if b:
            result.append(b)

The main *problem* with named subexpressions (aside from the potential
for side effects introduced by deliberately letting the name bindings
leak into the surrounding namespace) is that it introduces a
redundancy at the single assignment level since an expression
statement that names the expression would be equivalent to a simple
assignment statement:

   x = a
   (a as x)

On the other hand, there's a similar existing redundancy between
function definitions and binding lambda expressions to a name:

    f = lambda: None
    def f(): pass

And for that, we just have a PEP 8 style guideline recommending the
latter form. Something similar would likely work for saying "only use
named subexpressions in cases where using a normal assignment
statement instead would require completely restructuring the code".

Regards,
Nick.

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia


More information about the Python-ideas mailing list