On 15 February 2014 11:22, Chris Angelico <rosuav@gmail.com> wrote:
On Sat, Feb 15, 2014 at 12:12 PM, Nick Coghlan <ncoghlan@gmail.com> wrote:
On 15 February 2014 10:49, Chris Angelico <rosuav@gmail.com> wrote:
And that's my point. No matter how the *computer* sees them, the *programmer* sees them as peers. Adding an additional option to the list should not change the indentation level of any other, because the logical structure of the code hasn't changed.
You snipped the salient point in all this: the relevant case is one where the programmer wants to check *different* things, and *only* wants to calculate them if the earlier things are false. If they were true peers, this approach would work:
x = alternative_1() y = alternative_2() z = alternative_3()
if x: # Do something with x elif y: # Do something with y elif z: # Do something with z
I believe they're still peers; they just happen to be unable to fit into the physical structure of Python that way. Her's a concrete example: You have a series of regular expressions, and you want to process whichever one matches. No line of text is allowed to match more than one regex (to prevent excessive processing), but any line could match any regex.
if re1.match(line) as match: # do stuff with the match object elif re2.match(line) as match: # do different stuff, using the matched substrings # etc etc etc
This use case is a large part of why the "first" PyPI project exists and why itertools.first_true has been proposed for inclusion in the stdlib: http://bugs.python.org/issue18652 (a patch would help greatly in getting that to actually happen for 3.5) The re.match case would then be written as: match = first_true(pattern.match for pattern in patterns) If the handling is identical, there's no need for an if/elif chain at all, otherwise the revised if/elif chain is based on the attributes of the match object.
Adding another one is as simple as determining its position in the sequence (since earlier matches take precedence over later ones).
And with first_true, it's similarly simple (especially in the case where the patterns are different, but the handling is predominantly the same, since then it's just a matter of adding a new entry to the list of patterns).
Removing one is just deleting its elif and corresponding block of code. They are peers. The fact that Python doesn't currently have syntax that allows this *in an elif chain* doesn't change this; if you were to write it as pseudo-code, you would write them as peers. That's why the function-with-return or loop-with-break still looks better, because it structures the code the way that logically makes sense - flat, not nested.
That doesn't mean embedded assignments are the answer though - they're a sledgehammer solution that is tempting as a workaround for larger structural issues. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia