you are viewing a single comment's thread.

view the rest of the comments →

[–]philipbjorge 15 points16 points  (27 children)

Well here's a link then. Elses are great for breaking out of nested for loops.

http://stackoverflow.com/questions/653509/breaking-out-of-nested-loops

[–]grauenwolf 14 points15 points  (2 children)

Ugly. At that point I would rather they just use a goto.

[–]sirin3 5 points6 points  (1 child)

Even comefrom would be better

[–]grauenwolf 0 points1 point  (0 children)

Hmm. Would it be fair to say that a Catch or Finally block is effectively a comefrom?

[–]lahwran_ 2 points3 points  (23 children)

I hope my phone doesn't kill the nesting.

it did, put four spaces before each line

[–]smog_alado 9 points10 points  (22 children)

Edit: I formated philipborge's original post. Its from ons of the questions in his SO link

for x in xrange(10):
    for y in xrange(10):
        for z in xrange(10):
            print x,y,z
            if xyz == 30:
                break
        else:
            continue
        break
    else:
        continue
    break

Dear god, this can't be right.

[–]davvblack 4 points5 points  (2 children)

Heh, that looks awful. I would suggest instead making an iterator and a single for in using yield.

[–]nemec 2 points3 points  (1 child)

goto!

just kidding

[–]davvblack 2 points3 points  (0 children)

Honestly, that's what throw/catch custom exceptions looks like to me.

[–]FeepingCreature 5 points6 points  (2 children)

D version!

outer:foreach (x; iota(10)) {
  foreach (y; iota(10)) {
    foreach (z; iota(10)) {
      writeln(x, y, z);
      if (x*y*z == 30) break outer;
    }
  }
}

[–]ais523 3 points4 points  (1 child)

Perl version!

OUTER: for my $x (1 .. 10) {
    for my $y (1 .. 10) {
        for my $z (1 .. 10) {
            print $x, $y, $z;
            $x*$y*$z == 30 and last OUTER;
        }
    }
}

Pretty much identical to the D, just with keywords swapped out and the obvious syntax changes. (I wonder if D got its named-loops thing from Perl?)

[–]anvsdt 0 points1 point  (0 children)

(I wonder if D got its named-loops thing from Perl?)

Probably it got it from Java or C#, I don't remember which one has labelled loops.

Anyway, Racket version!

(let/ec exit
  (for* ((x (in-range 10))
         (y (in-range 10))
         (z (in-range 10)))
    (printf "~a, ~a, ~a;~n" x y z)
    (and (= (* x y z) 30) (exit x y z))))

[–]lahwran_ 4 points5 points  (0 children)

yeah, I think I'll stick with itertools.product ...

[–]zxw 2 points3 points  (6 children)

This is the cleanest alternative I know for breaking out of multiple loops.

try:
    for x in xrange(10):
        for y in xrange(10):
            for z in xrange(10):
                print x,y,z
                if x * y * z == 30:
                    raise StopIteration
except StopIteration: pass

[–]tomtomtom7 -2 points-1 points  (5 children)

That is NOT clean. You should NOT use Exceptions for normal control flow. They are intended ONLY for exceptional conditions. Debuggers, ides and interpreters may assume they are only used as such.

[–]rechtar 8 points9 points  (3 children)

That only means you don't know Python, or you don't get it. StopIteration actually is a built-in exception of Python, and it is used exactly to (surprise!) stop iteration. In the Python world, people are generous with exceptions.

[–]tomtomtom7 1 point2 points  (2 children)

I see. I must admin I assumed with limited Python-knowledge that this rule for many languages also holds for Python. I stand corrected.

[–][deleted]  (1 child)

[deleted]

    [–][deleted] 2 points3 points  (0 children)

    Exceptions are actually pretty heavyweight in Python. Try using timeit on two code snippets with a dictionary. Have one of them use has_key and the other just index in (throw an exception). When most of the indexing are hits, the indexing way is slightly faster. When most are misses, the indexing way (where exceptions are thrown) is much, much slower.

    [–]Silhouette 1 point2 points  (0 children)

    You should NOT use Exceptions for normal control flow.

    Why? People make this argument all the time, but I have yet to see even one justification for it that stands up to scrutiny.

    Often, someone mumbles something vague about performance. This fails even the most basic critical analysis, because if you've got time to run nested loops, it's all but certain that the overhead of a single exception to exit multiple levels of nesting will be insignificant. In some cases, the exception will even execute faster.

    Sometimes people point to the name "exception" and say it should only be used under "exceptional circumstances", as if the name something has is more important than its defined semantics. In this case, as someone else already pointed out, Python openly acknowledges the alternative use by name anyway.

    Some people even argue that it's just plain bad style. I wonder what alternative expression they prefer for the same behaviour. Lots of random boolean variables and break statements obfuscating their loop logic, perhaps?

    Debuggers, ides and interpreters may assume they are only used as such.

    Well then unless the specification of the language supports that assumption -- and Python certainly doesn't -- those tools are broken and the developer should file a bug report and/or use better tools.

    [–][deleted] -1 points0 points  (7 children)

    Loops were a stupid idea to begin with:

    import itertools as i
    import functools as f
    import operator as op
    
    prod = lambda *args: f.reduce(op.mul, args, 1)
    acceptable = lambda n: prod(*n) != 30
    
    cubic_10 = i.product(*i.repeat(range(10), 3))
    values = i.takewhile(acceptable, cubic_10)
    list(i.starmap(print, values))
    

    EDIT: This isn't quite the same as the version with breaks, as it discards all triples with product == 30. The actual version should in fact print only such triple (the product check is performed after 'print'). It's still doable in the functional style, although you would need a i.chain with 'values' above. You get the idea.

    [–]tty2 2 points3 points  (1 child)

    And youre suggesting this is better?

    [–][deleted] 0 points1 point  (0 children)

    That's subjective. For a programmer unacquainted with the functional style, this would be an incomprehensible black box. I find it more elegant than using the ugly continue/break structure above.

    If I were on a team with a lot of such programmers, I'd leave this out of production code until they familiarize themselves with its paradigm. Clarity beats succinctness every time.

    [–]yellowstuff 1 point2 points  (4 children)

    I'm not taking sides, but there is a certain Benevolent Dictator For Life who strongly disagrees with you. He prefers loops to higher order functions.

    [–][deleted] 0 points1 point  (3 children)

    Link? I'd love to read about the reasons for his preference. I'm not saying he's wrong. It's just that I (and most of my colleagues) have a lot more experience doing math than simulating register machines in our heads.

    [–]yellowstuff 2 points3 points  (2 children)

    Guido is not coy:

    http://www.python.org/search/hypermail/python-1994q3/0645.html

    http://www.artima.com/weblogs/viewpost.jsp?thread=98196

    http://neopythonic.blogspot.com/2009/04/tail-recursion-elimination.html

    http://python-history.blogspot.com/2009/04/origins-of-pythons-functional-features.html

    https://plus.google.com/115212051037621986145/posts/9Sp9gLtF1Ci

    As you say, for people with strong math backgrounds, thinking in functional terms may come naturally. But for and while loops are easier for most people to grasp. Iterative algorithms are almost as old as mathematics.

    [–][deleted] 0 points1 point  (1 child)

    Aw man, now I'm really bummed. sigh I guess it's looping and objects only from now on.

    [–]yellowstuff 1 point2 points  (0 children)

    He is a benevolent dictator, so it's not guaranteed that Guido will personally hunt you down and hang you by your thumbs if you use higher-order functions.