GOTO would make this code look better....



  • while True:
        seen={}
        for n,g in enumerate(out):
            for fn,(x,y) in g.items():
                seen[fn]=seen.get(fn,[])+[n]
    
        print 'Checking...',
    
        for n,g in enumerate(out):
            for fn,(x,y) in g.items():
                if len(seen[fn])==1:
                    continue
                break
            else:
                print n,
                continue
            print '*'
            out=domerge(out,seen[fn],fn)
            break
        else:
            print 'Done merging'
            break


  • If you squint a bit, you can almost see the goto else. What horrid abomination of a language is this? Else as a label? fn,[? True with one uppercase letter? Looks like bastard offspring from FORTRAN's and Scala's secret tryst. Ghastly.



  • @TGV said:

    What horrid abomination of a language is this? Else as a label?
     

    Python. The "for ... else" construct executes the "else" clause if the "for" loop terminates normally - that is, not via a "break".

    http://psung.blogspot.com/2007/12/for-else-in-python.html

     



  • @Wrongfellow said:

    Python. The "for ... else" construct executes the "else" clause if the "for" loop terminates normally - that is, not via a "break".

    Huh. That sort of almost makes sense, in that the "loop through list/break when found/else" construct is very common and usually a little clumsy in other languages (unless you have some kind of grep/map).

    But this particular solution, coupled with Python's unholy whitespace WTF, is almost illegible to anyone not Pythonified. Which begs another question: if a certain language construct isn't immediately obvious, or even confusing, should it be in the language? I think we can all think of certain things (yes, Larry Wall, I'm looking at you).



  • @Wrongfellow said:

    @TGV said:

    What horrid abomination of a language is this? Else as a label?
     

    Python. The "for ... else" construct executes the "else" clause if the "for" loop terminates normally - that is, not via a "break".

    http://psung.blogspot.com/2007/12/for-else-in-python.html

     

    ... that is the exact opposite behavior I would expect if you told me you could attach an "else" to a "for". They really should have chosen a new keyword for that, instead of overloading "else" in such a weird way.

    @b-redeker said:

    But this particular solution, coupled with Python's unholy whitespace WTF, is almost illegible to anyone not Pythonified. Which begs another question: if a certain language construct isn't immediately obvious, or even confusing, should it be in the language?

    Of course not. Languages are for human beings. Usability principles apply as much to programming languages as they do to anything else.



  • I've figured out WHY does it look like that, python can't break/continue any loop except he inner one, unlike some other languages. If you could specify which loop to break it would look much saner:

    while True:
    seen={}
    for n,g in enumerate(out):
    for fn,(x,y) in g.items():
    seen[fn]=seen.get(fn,[])+[n]

    print 'Checking...',
        for n,g in enumerate(out):
    for fn,(x,y) in g.items():
    if len(seen[fn])!=1:
    print '*'
    out=domerge(out,seen[fn],fn)
    [here would be something that would break the outer for... or continue the outer while... or just a fucking goto if python had one...]
    print n,
    else:
    print 'Done merging'
    break
    That would look atleast a bit saner, though still a WTF.
    @b-redeker said:
    Which begs another question: if a certain language construct isn't immediately obvious, or even confusing, should it be in the language?

    Hmmm by that logic we should remove 99% of Perl...

     

     

     



  • @blakeyrat said:

    @Wrongfellow said:

    @TGV said:

    What horrid abomination of a language is this? Else as a label?
     

    Python. The "for ... else" construct executes the "else" clause if the "for" loop terminates normally - that is, not via a "break".

    http://psung.blogspot.com/2007/12/for-else-in-python.html

     

    ... that is the exact opposite behavior I would expect if you told me you could attach an "else" to a "for". They really should have chosen a new keyword for that, instead of overloading "else" in such a weird way.

     

    I would've assumed that the else clause executed if the conditional in the for loop were never true. This is evil.



  • @blakeyrat said:

    @Wrongfellow said:

    @TGV said:

    What horrid abomination of a language is this? Else as a label?
     

    Python. The "for ... else" construct executes the "else" clause if the "for" loop terminates normally - that is, not via a "break".

    http://psung.blogspot.com/2007/12/for-else-in-python.html

     

    ... that is the exact opposite behavior I would expect if you told me you could attach an "else" to a "for". They really should have chosen a new keyword for that, instead of overloading "else" in such a weird way.

     

    I've never done python, but apparently it does what I expected that to mean.  What would you expect it to do?  I can't figure out what the opposite of my expected behavior would be.



  • @locallunatic said:

    @blakeyrat said:
    ... that is the exact opposite behavior I would expect if you told me you could attach an "else" to a "for". They really should have chosen a new keyword for that, instead of overloading "else" in such a weird way.
     

    I've never done python, but apparently it does what I expected that to mean.  What would you expect it to do?  I can't figure out what the opposite of my expected behavior would be.

    Well, it's kind of hard to verbalize, but normally "else" is "if that doesn't work, then do this." The problem is, in my brain, if the loop completes without calling "break" then it "works". If it calls break, then it "doesn't work" and should execute the else clause.

    I don't really have any issue with the construct of "do this code if the loop breaks", but using the keyword "else" for it confuses the bejeebers out of me. And then there's stuff like... if you break out of a loop, but the loop was finished anyway-- do you get the else?

    Frankly, I like the JS solution with labels much better. And I wager that was already well-established before this design work began on Python.


    Edit: actually, let's do this: translate this into english. "else" is generally translated to "otherwise" like so:

    "If you have a car, go to the first line. Otherwise, go to the second line."

    This usage translates into something like:

    "Go put a napkin on every plate. Otherwise, wash the dishes." In English, it just doesn't make sense... it's a WTF. Otherwise WHAT?



  • @blakeyrat said:

    Well, it's kind of hard to verbalize, but normally "else" is "if that doesn't work, then do this." The problem is, in my brain, if the loop completes without calling "break" then it "works". If it calls break, then it "doesn't work" and should execute the else clause.

    I don't really have any issue with the construct of "do this code if the loop breaks", but using the keyword "else" for it confuses the bejeebers out of me.

    +1.

    +<FONT color=#0000ff size=2><FONT color=#0000ff size=2>double</FONT></FONT><FONT size=2>.PositiveInfinity</FONT>, actually.



  • @blakeyrat said:

    Well, it's kind of hard to verbalize, but normally "else" is "if that doesn't work, then do this." The problem is, in my brain, if the loop completes without calling "break" then it "works". If it calls break, then it "doesn't work" and should execute the else clause.
     

    OK, I can see that.  I guess I just normally think of "break" as short cut out (basically goto after loop) rather than issue in doing loop.  Reason I read it my way was 'cause for loops are just a compacted while loop (and to me an else seems like a useful thing there).



  • @locallunatic said:

    @blakeyrat said:

    Well, it's kind of hard to verbalize, but normally "else" is "if that doesn't work, then do this." The problem is, in my brain, if the loop completes without calling "break" then it "works". If it calls break, then it "doesn't work" and should execute the else clause.
     

    OK, I can see that.  I guess I just normally think of "break" as short cut out (basically goto after loop) rather than issue in doing loop.  Reason I read it my way was 'cause for loops are just a compacted while loop (and to me an else seems like a useful thing there).

    Well, it depends on the kind of loop. You can write a loop that says "do X to everything" (Type 1) or you can write a loop that says "try to find X in everything" (Type 2). In the latter case, this use of "else" makes a lot more sense because you break out of the loop when you successfully find the X.

    The problem is, I wager that Type 2 is a lot less used than Type 1. Usually if you're trying to find X in a bunch of Xs, that bunch is in an indexed data type that doesn't require (explicitly) looping through to find. What I mean is, instead of "foreach( blah in blahs ) { if( blahs.x == x) {break;} };" you write something like "blahs.find(x)" or "blahs.hasIndex(x)" or "if blahs[x] != null". In fact, I'd argue that you should nearly *never* have to loop through a list to find an item in it.

    So given that, the most popular kind of loop would be Type 1. Type 1 loops are like my English example, "go to every plate and put a napkin on it." In this case, "break" doesn't indicate "we finished successfully", it indicates "something went wrong and I can't continue." And for this type of loop, that "else" clause makes no sense.



  • @TGV said:

    fn,[?

    That bit looks like CS mangling to me.

     



  • @blakeyrat said:

    Well, it depends on the kind of loop. You can write a loop that says "do X to everything" (Type 1) or you can write a loop that says "try to find X in everything" (Type 2).
     

    I guess personal experience is throwing me from the standard cases as I normally end up with type 3 loops (1+2 due to stupid business rules).



  •  Another example debunking the myth how Python magically brings in readability. Don't get me wrong, it's my favourite language and I consider 95% of it a masterpiece of language design (and I have no idea how to do those 5% better). I just can't stand language fanboys and vastly exaggerating advertising.

    As for the else on loops (yes, it exists for both kinds of loops): The reasoning is that the suite of else is executed only when the "condition" is true - i.e. when a while loops end normally, the condition became false -> no else; likewise for for-loops - when there is no more "x in xs", execution skips beyond the else. Doesn't make it any more intuitive, yes. But it is logically consistent, if you're willing to take interpret else this way and take the idea this far.



  • @metax said:

     Another example debunking the myth how Python magically brings in readability. Don't get me wrong, it's my favourite language and I consider 95% of it a masterpiece of language design (and I have no idea how to do those 5% better). I just can't stand language fanboys and vastly exaggerating advertising.

    As for the else on loops (yes, it exists for both kinds of loops): The reasoning is that the suite of else is executed only when the "condition" is true - i.e. when a while loops end normally, the condition became false -> no else; likewise for for-loops - when there is no more "x in xs", execution skips beyond the else. Doesn't make it any more intuitive, yes. But it is logically consistent, if you're willing to take interpret else this way and take the idea this far.

     

    After long and careful consideration all my criticisms of python can be summed up thusly: Misspelling a varible name should never be a runtime error!



  • @b-redeker said:

    But this particular solution, coupled with Python's unholy whitespace WTF, is almost illegible to anyone not Pythonified.

    While the solution is a bad one, the else block is no more mysterious than one used in an if block. I also love how everyone whines about whitespace in python...until they actually use the language! After that you realize how ridiculously verbose braces are and you also appreciate the fact that the language forces even the novice, to indent their code properly.



  • @esoterik said:

    After long and careful consideration all my criticisms of python can be summed up thusly: Misspelling a varible name should never be a runtime error!

    This isn't an issue with python, it's an issue with dynamic languages in general. If you don't like it, use a static language.



  •  @metax said:

     Another example debunking the myth how Python magically brings in readability.

    Well you could re-write that code in any { }-based language and it would be even less readable ;)



  • @bdew said:

    @b-redeker said:
    Which begs another question: if a certain language construct isn't immediately obvious, or even confusing, should it be in the language?

    Hmmm by that logic we should remove 99% of Perl...

    Yes.

    @bdew said:

     @metax said:

     Another example debunking the myth how Python magically brings in readability.

    Well you could re-write that code in any { }-based language and it would be even less readable ;)

    No.



  • @bdew said:

    @metax said:
     Another example debunking the myth how Python magically brings in readability.

    Well you could re-write that code in any { }-based language and it would be even less readable ;)

    Well, no. Most languages have either goto or multi-level break (or both), that would make the code look better. Python does not. So the language limitations that usually help readability harm it in this case.

    It would still be possible to write cleaner code in this case by wrapping the two nested loops in a local function (which conveniently happens to be closure in python) and using return instead of break, but it's not exactly the first thing that comes to one's mind when writing it.



  • What does this code do, exactly? From what I can see with my limited knowledge of Python, it takes a list of lists and sets "out" to something involving "domerge" based on the first list which contains no values which are repeated in that list or any of the others. A bit like this Perl version:

    while (1)
    {
        my %seen;
        for my $n (0..$#out)
        {
            for my $fn (@{$out[$n]})
            {
                $seen{$fn} = [(exists $seen{$fn} ? @{$seen{$fn}} : ()), $n];
            }
        }
        print "Checking...\n";

        for my $n (0..$#out)
        {
            use List::Util;
            if (first {@{$seen{$_}} > 1} @{$out[$n]})
            {
                print "$n\n";
            }
            else
            {
                print "*\n";
                @out = domerge @out, %seen;
                print "Done merging\n";
                last
            }
        }
    }

    I take it there's something else going on, as nothing good can happen in this code on subsequent runs through the [code]while (1)[/code] loop.



  • @Soviut said:

    @esoterik said:
    After long and careful consideration all my criticisms of python can be summed up thusly: Misspelling a varible name should never be a runtime error!

    This isn't an issue with python, it's an issue with dynamic languages in general. If you don't like it, use a static language.

    At least Python is sensible enough to give you an error about it instead of silently evaluating the non-existent variable to null, undefined or whatever. Provided it's not in an assignment. And even then you might get an error if it's the first assignment and you try to access the variable before the next one.



  • @metax said:

    As for the else on loops (yes, it exists for both kinds of loops): The reasoning is that the suite of else is executed only when the "condition" is true - i.e. when a while loops end normally, the condition became false -> no else; likewise for for-loops - when there is no more "x in xs", execution skips beyond the else. Doesn't make it any more intuitive, yes. But it is logically consistent, if you're willing to take interpret else this way and take the idea this far.

    See, to me that's not consistent or logical, it's exactly the opposite.

    Going from (using the braces syntax which I'm more familiar with)

    if (a) {
       // executes if a == true
    } else {
       // executes if a == false
    }

    to

    while (a) {
       // executes *as long as* a == true
    } else {
       // ???
    }
    
    and accepting the interpretation that the else branch is (or is not) evaluated after (and not instead of) the main branch having been (or not been) evaluated depending on the condition, I would instinctively expect "???" to be something like "executes if a == false after the end of the while loop". But if I understood what's been said about the way Python does things correctly, that's exactly the opposite of what happens:
    • If the loop terminates normally (which means a is now false) the else branch would not evaluated.
    • If the loop has been broken out of (which means a may - but does not necessarily have to be - still be true) but the else branch would be executed (independent of the actual value of a?)
    For me, that's completely counter-intuitive, and I don't see any logical reasoning for doing it that way...


  • @bdew said:

    @b-redeker said:
    Which begs another question: if a certain language construct isn't immediately obvious, or even confusing, should it be in the language?

    Hmmm by that logic we should remove 99% of Perl...

    Exactly. And then C and Java too. Such awfully confusing languages!



  • @Faxmachinen said:

    @bdew said:

    @b-redeker said:
    Which begs another question: if a certain language construct isn't immediately obvious, or even confusing, should it be in the language?

    Hmmm by that logic we should remove 99% of Perl...

    Exactly. And then C and Java too. Such awfully confusing languages!

    From a maintainability perspective, understandable code is king. Often programmers will come from a different background (we're talking about the real world, remember) and if code resembles line noise to them, that's a bad start (ie it will lead to unforced errors). If you add new possibilities to a language, ideally they should instantly make sense.

    Then again, it's not necessarily bad if you have to invest a little time to understand things. Which is why I posed it as a question.

    As for Perl, that's a great example. I've learned to use it and I love the power of it. A line like

    @files = map {"$dir/$_"} grep /\.xml$/, readdir DIR;
    makes instant sense to me. But I know very well that it might be a total nightmare for my successor.


  • @b-redeker said:

    As for Perl, that's a great example. I've learned to use it and I love the power of it. A line like
    @files = map {"$dir/$_"} grep /\.xml$/, readdir DIR;
    makes instant sense to me. But I know very well that it might be a total nightmare for my successor.
    Map, grep and readdir are built-in functions though, not language constructs. And even if I'm wrong, they're still pretty obvious (except grep). Perl can be confusing for many reasons, but its language constructs aren't major contributors.
     
    Edit: Here's the same code without some of the shortcuts:
    @files = map("$dir/$_", grep(/\.xml$/, readdir(DIR)));


  • @Faxmachinen said:

    Map, grep and readdir are built-in functions though, not language constructs.

    You're missing the point. The point is that it will confuse the crap out of quite a few people, so you have to be careful using it.

    So back to the original point. Say you're designing a language. You have a fantastic idea that will take programming to the next level, once people get it. However, you also know many people will NOT get it. What do you do? And I ask that because I have no clear answer.



  • @b-redeker said:

    So back to the original point. Say you're designing a language. You have a fantastic idea that will take programming to the next level, once people get it. However, you also know many people will NOT get it. What do you do? And I ask that because I have no clear answer.

    Depends on who you are:

    If you're designing Perl 6, you throw it in along with the kitchen sink.

    If you're designing C++0x, you make some noise about how complex the language is getting, then throw it in anyway.

    If you're designing Java-- haha! Just kidding! Java doesn't get new features, silly!

    If you're designing C#, then you tinker with it to get the syntax as easy and familiar as possible, borrowing from other familiar languages if needed-- if you can't pull it off, bye-bye feature, if you can you get something like Linq which everybody loves.



  • @b-redeker said:

    You're missing the point. The point is that it will confuse the crap out of quite a few people, so you have to be careful using it.

    Then I'm not sure why you quoted your original point about languages to make a different one about code.

    @b-redeker said:

    So back to the original point. Say you're designing a language. You have a fantastic idea that will take programming to the next level, once people get it. However, you also know many people will NOT get it. What do you do? And I ask that because I have no clear answer.

    The very nature of being a programming language makes a lot of people not get it; that's why you're earning more than the average McDonalds employee. You should just avoid syntax and keywords whose connotation is not intuitive (e.g. for/else), so you don't throw off those who do get it.



  • @Anonymouse said:

    while (a) {
    // executes as long as a == true
    } else {
    // ???
    }

    Perhaps an easier way to understand the benefit is with templating languages (note, thr {{ }} denotes an eval or print, such is the case in Django, GAE and Jinja templates):

    {% for item in items %}
       {{ item }}
    {% else %}
       No items in this list.
    {% endfor %}
    

    Which greatly simplifies the common construct:

    {% if items %}
        {% for item in items %}
            {{ item }}
        {% endfor %}
    {% else %}
        No items in this list.
    {% endif %}
    


  • I think this fits Congress's definition of "obscenity"... W00t!!!

    The Hicklin test was "whether the tendency of the matter charged as obscenity is to deprave and corrupt those whose minds are open to such immoral influences, and into whose hands a publication of this sort may fall."

    Anyone? Anyone? ...Bueller?



  • @blakeyrat said:

    @b-redeker said:
    So back to the original point. Say you're designing a language. You have a fantastic idea that will take programming to the next level, once people get it. However, you also know many people will NOT get it. What do you do? And I ask that because I have no clear answer.

    Depends on who you are:

    If you're designing Perl 6, you throw it in along with the kitchen sink.

    If you're designing C++0x, you make some noise about how complex the language is getting, then throw it in anyway.

    If you're designing Java-- haha! Just kidding! Java doesn't get new features, silly!

    If you're designing C#, then you tinker with it to get the syntax as easy and familiar as possible, borrowing from other familiar languages if needed-- if you can't pull it off, bye-bye feature, if you can you get something like Linq which everybody loves.

    blakey, I disagree with you on a number of things, but on this point I concur completely. C# is quite simply the best language around today, purely because Microsoft has made such an effort to make it so. It's easily readable, easily writable, has lovely and simple syntax, and of course, LINQ. The FOSS crowd loves to point and laugh at MS, but what they seem to (perennially) forget is that when MS decides to do something and do it right, they get it right.

    Also, I don't knows about Perl being "designed"... my conception of it (and Python and most other dynamically-typed languages) is of an organic mass growing larger and larger over time with no direction. (Kinda like the necromorphs from Dead Space, if you've played that game.)



  • @Soviut said:

    @Anonymouse said:
    while (a) {
    // executes as long as a == true
    } else {
    // ???
    }

    Perhaps an easier way to understand the benefit is with templating languages (note, thr {{ }} denotes an eval or print, such is the case in Django, GAE and Jinja templates):

    {% for item in items %}
       {{ item }}
    {% else %}
       No items in this list.
    {% endfor %}
    

    Which greatly simplifies the common construct:

    {% if items %}
        {% for item in items %}
            {{ item }}
        {% endfor %}
    {% else %}
        No items in this list.
    {% endif %}
    

    That's NOT equivalent to the python meaning. In python the else: block evaluates unless the loop was aborted by break.



  • @metax said:

     Another example debunking the myth how Python magically brings in readability. Don't get me wrong, it's my favourite language and I consider 95% of it a masterpiece of language design (and I have no idea how to do those 5% better). I just can't stand language fanboys and vastly exaggerating advertising.

    As for the else on loops (yes, it exists for both kinds of loops): The reasoning is that the suite of else is executed only when the "condition" is true - i.e. when a while loops end normally, the condition became false -> no else; likewise for for-loops - when there is no more "x in xs", execution skips beyond the else. Doesn't make it any more intuitive, yes. But it is logically consistent, if you're willing to take interpret else this way and take the idea this far.


    No. It executes the else when the condition is false. So it's executed when the loop did finish normally and not executed if it was broken out. Quoting from the manual:
    @http://docs.python.org/py3k/reference/compound_stmts.html#the-while-statement said:
    The while statement is used for repeated execution as long as an expression is true:

    while_stmt ::=  "while" expression ":" suite
                    ["else" ":" suite]
    

    This repeatedly tests the expression and, if it is true, executes the first suite; if the expression is false (which may be the first time it is tested) the suite of the else clause, if present, is executed and the loop terminates.



  • @Bulb said:

    It executes the else when the condition is false. So it's executed when the loop did finish normally and not executed if it was broken out.

    Ah-HA! So it does work the way I would expect it to, as outlined in my previous post above? My world view is restored, Hooray! :D



  • @The_Assimilator said:

    Also, I don't knows about Perl being "designed"... my conception of it (and Python and most other dynamically-typed languages) is of an organic mass growing larger and larger over time with no direction. (Kinda like the necromorphs from Dead Space, if you've played that game.)

    Perl 6 is (supposedly) being "designed". Which is why it's been like 12 years and still no release. And why it's not compatible at all with Perl 5. Hm... this also kind of reminds me of... C++0x! Which is in the exact same position...

    I haven't played Dead Space. But what you describe sounds like the aliens from System Shock 2.

    Edit: I'm actually surprised no Javanauts have come challenging that.


Log in to reply