[Python-ideas] If branch merging

Steven D'Aprano steve at pearwood.info
Mon Jun 8 04:18:30 CEST 2015


On Sun, Jun 07, 2015 at 07:06:42PM -0600, Cory Beutler wrote:

[...]
> The functionally is not the same. In your example 'foo' gets called even if
> none of the conditions are true. The above example only runs 'foo' if it
> enters one of the if-blocks.

Ah yes, of course you are correct.


> > > *Many nested 'if' statements could now be a more linear style:*
> > > # Old Version
> > > if a == b:
> > >     print ('a == b')
> > >     if b == c:
> > >         print ('b == c')
> > >     print ('end if')
> >
> > What's wrong with that code? Nesting the code like that follows the
> > logic of the code: the b==c test *only* occurs if a==b.
> >
> >
> > > # New Version
> > > if a == b:
> > >     print ('a == b')
> > > alif b == c:
> > >     print ('b == c')
> > > also:
> > >     print ('end if')
> >
> > I consider this significantly worse. It isn't clear that the comparison
> > between b and c is only made if a == b, otherwise it is entirely
> > skipped.
> >
> >
> It may only be worse because you are not used to reading it. This type of
> syntax looks simple once you know how the pieces work. I mean, you know
> that having multiple if-elif statements will result in only checking
> conditions until one passes. The 'also' mentality would be the same, but
> backwards.

In the first case, your b==c test only occurs if a==b, which can be 
easily seen from the structure of the code:

if a == b:
    everything here occurs only when a == b
    including the b == c test


In the second case, there is no hint from the structure:

if a == b:
    ...
alif b == c:

As you read down the left hand column, you see "if a == b" and you can 
mentally say "that block only occurs if a == b" and move on. But when 
you get to the alif block, you have to stop reading forward and go back 
up to understand whether it runs or not.

It's not like elif, which is uneffected by any previous if or elif 
clauses. Each if/elif clause is independent. The test is always made 
(assuming execution reaches that line of code at all), and you can 
decide whether the block is entered or not by looking at the if/elif 
line alone:

...
elif some_condition():
    block

Here, nothing above the "elif" line matters. If I reach that line, 
some_condition() *must* be evaluated, and the block entered if it 
evaluates to a truthy value. It's easy to understand. But:

...
alif some_condition():
    block


I cannot even tell whether some_condition() is called or not. The 
structure gives no hint as to whether the alif line is reachable. It 
looks like it is at the same semantic level as the distant "if" 
line somewhere far above it, but it isn't. Whether it runs or 
not is dependent on the distant "if" and "elif" lines above it.

By it's nature, this cannot be simple, since it introduces coupling 
between the alif line you are reading and one or more distant lines 
above it, while disguising the structure of the code by aligning the 
alif with the if even though it is conceptually part of the if block.


-- 
Steve


More information about the Python-ideas mailing list