As was foretold, we've added advertisements to the forums! If you have questions, or if you encounter any bugs, please visit this thread: https://forums.penny-arcade.com/discussion/240191/forum-advertisement-faq-and-reports-thread/
We're funding a new Acquisitions Incorporated series on Kickstarter right now! Check it out at https://www.kickstarter.com/projects/pennyarcade/acquisitions-incorporated-the-series-2

My Little [Programming] Thread: Debugging is Magic

17677798182100

Posts

  • KambingKambing Registered User regular
    LD50 wrote: »
    I don't find prototypes to offer anything over open classes myself.
    For me, it's about pedagogy. Classes (in the context of statically-typed languages) define strong interfaces between components. However, that's antithetical to the dynamically-typed nature of Python and Ruby. In those languages, objects are simple dictionaries and the class construct gives some (slight) convenience for initially populating those dictionaries. I don't like conflating the two concepts (class-as-interface, class-as-convenience) together. The one thing I appreciate about Javascript is that it embraces its dynamic-typedness and does not go down this route.

    @TwitchTV, @Youtube: master-level zerg ladder/customs, commentary, and random miscellany.
  • ecco the dolphinecco the dolphin Registered User regular
    Oh god our hardware guy is too good.

    He's got the new hardware ready for programming and I haven't even begun on the bootloader yet to configure our DDR controller.

    So, this is how our game is to be played, eh? Efficiently!

    I'm watching you, hardware guy.

    Penny Arcade Developers at PADev.net.
    CampyNightslyr
  • MahnmutMahnmut Registered User regular
    Oh god our hardware guy is too good.

    He's got the new hardware ready for programming and I haven't even begun on the bootloader yet to configure our DDR controller.

    So, this is how our game is to be played, eh? Efficiently!

    I'm watching you, hardware guy.

    Now imagining that you work in Konami's arcade hardware division. Shhh, it's OK, don't disillusion me.

    Steam/LoL: Jericho89
    ecco the dolphin
  • Alistair HuttonAlistair Hutton Dr EdinburghRegistered User regular
    Duh, of course I wanted product. That was dumb of me.

    I have a thoughtful and infrequently updated blog about games http://whatithinkaboutwhenithinkaboutgames.wordpress.com/

    I made a game, it has penguins in it. It's pay what you like on Gumroad.

    Currently Ebaying Nothing at all but I might do in the future.
  • Apothe0sisApothe0sis Have you ever questioned the nature of your reality? Registered User regular
    Version control - can anyone recommend a quickstart guide? Specifically one that goes over the theory and conventions? Like "you should commit under these scenarios. Here's what the buzzwords mean" and that sort of thing.

  • bowenbowen How you doin'? Registered User regular
    not a doctor, not a lawyer, examples I use may not be fully researched so don't take out of context plz, don't @ me
    Apothe0sis
  • JasconiusJasconius sword criminal mad onlineRegistered User regular
    you should commit under the scenario that you did something you want to save, for starters

    then, upon attaining mastery, start committing individual pieces of functionality

    small commits help me a lot in large system debugging because when something fucked up happened, I can look at the last 24 hour of commits and see exactly what has changed in an otherwise stable system to cause bugs... in addition to normal debugging routines

    bowenEchoecco the dolphin
  • urahonkyurahonky Registered User regular
    I try to commit what I have when I leave for the day if and ONLY if it doesn't break the build. I try to live under the idea that I could be hit by a bus on the way home.

  • bowenbowen How you doin'? Registered User regular
    Jasconius wrote: »
    you should commit under the scenario that you did something you want to save, for starters

    then, upon attaining mastery, start committing individual pieces of functionality

    small commits help me a lot in large system debugging because when something fucked up happened, I can look at the last 24 hour of commits and see exactly what has changed in an otherwise stable system to cause bugs... in addition to normal debugging routines

    That is the best part. Then rolling back if you need to.

    not a doctor, not a lawyer, examples I use may not be fully researched so don't take out of context plz, don't @ me
  • bowenbowen How you doin'? Registered User regular
    I try not to roll back though, it's so cludgy versus just patching what I think was broken.

    not a doctor, not a lawyer, examples I use may not be fully researched so don't take out of context plz, don't @ me
  • JasconiusJasconius sword criminal mad onlineRegistered User regular
    i think i've only done a true rollback once in my life

    but the record of line changes is useful

    bowen
  • bowenbowen How you doin'? Registered User regular
    urahonky wrote: »
    I try to commit what I have when I leave for the day if and ONLY if it doesn't break the build. I try to live under the idea that I could be hit by a bus on the way home.

    I live under the premise that this is not my problem, and that if a programmer can't figure it out, welp, sucks to be them.

    not a doctor, not a lawyer, examples I use may not be fully researched so don't take out of context plz, don't @ me
    a5ehren
  • hsuhsu Registered User regular
    @Apothe0sis‌, what version control system do you currently use?
    Because, after having used GIT for the past 2 years, I would jump ship back to Subversion in a heartbeat.
    http://www.thegeekstuff.com/2011/04/svn-command-examples/
    I try to commit at least once a day.
    For major changes, this means splitting up my work into smaller chunks, where sometimes those small chunks aren't even referenced, so I can safely commit it, without breaking the build or unit tests.

    iTNdmYl.png
  • InfidelInfidel Heretic Registered User regular
    I commit for each issue, with the relevant tracking numbers, so that anyone with the number can see exactly what I did to address the specific issue. Handy when it crops up elsewhere and someone is reading past defects on how it was fixed.

    For new projects or features, I commit once I am happy with my own testing. After that every change is a request/fix with a tracking number and we do the above.

    OrokosPA.png
    bowenecco the dolphina5ehren
  • gavindelgavindel The reason all your software is brokenRegistered User regular
    Commits? Oh, yes, commits.

    For the first month I worked here, I thought the depot saved things automatically. Nope.

    For the next month, I thought I was successfully syncing with the depot, but was actually saving to the local depot file on my machine.

    Tomorrow is my last day, so I think I'm going to convert my project to one giant notepad file and email it to my project manager.

    Angels, innovations, and the hubris of tiny things: my book now free on Royal Road! Seraphim
    undergroundmonorailecco the dolphin
  • Alistair HuttonAlistair Hutton Dr EdinburghRegistered User regular
    Kambing wrote: »
    Ethea wrote: »
    I want to do something in Python that seems like it should be a solved problem what with the itertools library

    I have two lists:

    a = [A,B,C,D]
    b = [1,2]

    I want the output to be (in the case of these lists)

    (A,1),(A,2),(B,1),(B,2),(C,1),(C,2),(D,1),(D,2)

    but b could sometimes be the empty list and in those cases the output should be

    (A,None),(B,None),(C,None),(D,None)

    I started trying something with zip_longest but that was a non starter. Obviously I can write this code myself but it feels like something the should just be a couple of nested function calls.

    @Alistair Hutton‌ You want the cross product of the two iterators, which is the product() call in itertools (https://docs.python.org/2/library/itertools.html#itertools.product) .

    The one liner using product():
    product(a, [None] if len(b) == 0 else b)
    

    Work colleague points out this could be made lovlier with a simple
    product(a, b or [None])
    

    Such elegance, much terseness, wow

    I have a thoughtful and infrequently updated blog about games http://whatithinkaboutwhenithinkaboutgames.wordpress.com/

    I made a game, it has penguins in it. It's pay what you like on Gumroad.

    Currently Ebaying Nothing at all but I might do in the future.
    gavindelInfidelMahnmutmightyjongyoan_alt
  • KambingKambing Registered User regular
    Kambing wrote: »
    Ethea wrote: »
    I want to do something in Python that seems like it should be a solved problem what with the itertools library

    I have two lists:

    a = [A,B,C,D]
    b = [1,2]

    I want the output to be (in the case of these lists)

    (A,1),(A,2),(B,1),(B,2),(C,1),(C,2),(D,1),(D,2)

    but b could sometimes be the empty list and in those cases the output should be

    (A,None),(B,None),(C,None),(D,None)

    I started trying something with zip_longest but that was a non starter. Obviously I can write this code myself but it feels like something the should just be a couple of nested function calls.

    @Alistair Hutton‌ You want the cross product of the two iterators, which is the product() call in itertools (https://docs.python.org/2/library/itertools.html#itertools.product) .

    The one liner using product():
    product(a, [None] if len(b) == 0 else b)
    

    Work colleague points out this could be made lovlier with a simple
    product(a, b or [None])
    

    Such elegance, much terseness, wow

    Ugh. I find that code rather gross. But that stems from the weirdness involving `or` producing non-boolean values in order to facilitate (insignificant) syntactic conveniences like this.

    @TwitchTV, @Youtube: master-level zerg ladder/customs, commentary, and random miscellany.
  • JasconiusJasconius sword criminal mad onlineRegistered User regular
    Are there are any good studies of language performance in the C++/C#/Java realm that look at usage of std:: in C++ versus "raw" C/C++ usage?

    My basic question, does liberal use of std:: negate the performance benefits of C++ over C# and Java?

  • NightslyrNightslyr Registered User regular
    Programming/design question:

    I've been tasked with creating a thing that will download some records in the DB as either a csv or txt file. The records, however, could change in a couple different ways over time (column values change, more records added, that sort of thing). So, I'm wondering if it's possible to create something that can run through the records and create the necessary file in memory, then have it download to the client without me actually having to save a hard copy of these files on the web server. I guess that might be considered a file stream, or something? I don't usually work with files, so I'm a bit clueless in that regard.

    I'm using PHP :rotate: like always, so I'm not sure if it has the capabilities to do what I want.

    PSN/XBL/Nintendo/Origin/Steam: Nightslyr 3DS: 1607-1682-2948
    Switch: SW-3515-0057-3813 FF XIV: Q'vehn Tia
  • hsuhsu Registered User regular
    Infidel wrote: »
    I commit for each issue, with the relevant tracking numbers, so that anyone with the number can see exactly what I did to address the specific issue. Handy when it crops up elsewhere and someone is reading past defects on how it was fixed.

    For new projects or features, I commit once I am happy with my own testing. After that every change is a request/fix with a tracking number and we do the above.
    I used to commit this way, but after working on larger projects, I found that this way leads to integration problems, and thus, more work on your side.

    In larger projects, multiple people end up working on the same code base, sometimes interfering with each other. The best way to deal with this is to commit often, daily or at minimum, every other day, to force more frequently, smaller merges.

    You end up doing less work overall, if your commits are earlier, since your merge difference will be smaller. Plus it gives you the advantage over people who like to merge late, or with big changes, as they have to merge their code with yours, not the other way around, which puts the effort on them, rather than on you.

    iTNdmYl.png
  • urahonkyurahonky Registered User regular
    Jesus Christ.

    Manager: "Hey urahonky, do you think you can get chart colors working by Friday?"
    Me: "Yeah now that the service auto-deploys and it's up on the environment it shouldn't be a problem."

    Guess what is broken? Auto-deployments. Guess how much work I have been able to finish on the colors today?

    0%.

    gavindelmightyjongyoVegemyte
  • KambingKambing Registered User regular
    edited August 2014
    Jasconius wrote: »
    Are there are any good studies of language performance in the C++/C#/Java realm that look at usage of std:: in C++ versus "raw" C/C++ usage?

    My basic question, does liberal use of std:: negate the performance benefits of C++ over C# and Java?

    In short no, but from the research that we've conducted (bringing efficient memory safety to C++), using std:: does not impact runtime performance versus comparable use of standard libraries in other languages. The performance delta in C++ versus Java that we observed was from memory locality and cache-friendliness, in particular, abuse of heap allocations.

    EDIT: as a concrete example, if you go full std:: and, e.g., use std::vector with std::iterator to walk over the list, the performance footprint after template expansion and subsequent optimization is literally pointer-over-array as you would expect. In contrast with Java, the iterator object constitutes a heap-allocated object that you must explicitly walk through in order to access the underlying array.

    Kambing on
    @TwitchTV, @Youtube: master-level zerg ladder/customs, commentary, and random miscellany.
    Ethea
  • InfidelInfidel Heretic Registered User regular
    hsu wrote: »
    Infidel wrote: »
    I commit for each issue, with the relevant tracking numbers, so that anyone with the number can see exactly what I did to address the specific issue. Handy when it crops up elsewhere and someone is reading past defects on how it was fixed.

    For new projects or features, I commit once I am happy with my own testing. After that every change is a request/fix with a tracking number and we do the above.
    I used to commit this way, but after working on larger projects, I found that this way leads to integration problems, and thus, more work on your side.

    In larger projects, multiple people end up working on the same code base, sometimes interfering with each other. The best way to deal with this is to commit often, daily or at minimum, every other day, to force more frequently, smaller merges.

    You end up doing less work overall, if your commits are earlier, since your merge difference will be smaller. Plus it gives you the advantage over people who like to merge late, or with big changes, as they have to merge their code with yours, not the other way around, which puts the effort on them, rather than on you.

    That's what I'm talking about, versus arbitrary "commit end of day errrr week?" type stuff some people do.

    Our commits are feature/fix based and that's almost always easier to integrate than a whole dump of unrelated changes that are only tied together because the same person did them that week.

    OrokosPA.png
    EtheaEcho
  • BarrakkethBarrakketh Registered User regular
    Kambing wrote: »
    Ugh. I find that code rather gross. But that stems from the weirdness involving `or` producing non-boolean values in order to facilitate (insignificant) syntactic conveniences like this.
    I don't have a problem with it myself, 'or' returns a value that will evaluate to True or False (if it looks like a duck and quacks like a duck...).

    I wonder if it would be valid C to use the ternary operator to do the same thing...

    Rollers are red, chargers are blue....omae wa mou shindeiru
    undergroundmonorailLD50
  • JasconiusJasconius sword criminal mad onlineRegistered User regular
    i only do the once daily commit on things I don't care about or are unlikely to be rolled back or conflict ever

    anything remotely sensitive i will do atomic commits, or nearly-atomic commits.... not tied to any specific ticket number, but just functionally related

  • KambingKambing Registered User regular
    edited August 2014
    Barrakketh wrote: »
    Kambing wrote: »
    Ugh. I find that code rather gross. But that stems from the weirdness involving `or` producing non-boolean values in order to facilitate (insignificant) syntactic conveniences like this.
    I don't have a problem with it myself, 'or' returns a value that will evaluate to True or False (if it looks like a duck and quacks like a duck...).

    I wonder if it would be valid C to use the ternary operator to do the same thing...

    The types don't line up. 'or' takes two things that are (convertible to a) bool and produces a bool. In Python, 'or' takes two things that are (convertible to a bool) and produces a value that is convertible to a bool. More precisely, the type is:
    Boolable a, Boolable b => a -> b -> a | b
    

    Where a | b is the union type because the type of the result of `or` depends on which of the operands is selected. C/C++ doesn't allow this directly because a | b is not a valid type in the language, although you can use unions to achieve the same effect.

    EDIT: related, when both operands are false, then `or` is defined to not return False but b instead. This sort of makes sense for `or`, but by symmetry, `and` returns the a value by default. Then you get weird situations like this:
    >>> x = []
    >>> y = []
    >>> z = x and y    # Hrm, what is z referring to?
    >>> x.append(1)
    >>> y.append(2)
    >>> z
    [1]
    

    The definition of `or` in Python is consistent but not what I would call sensible. Similarly to this in Javascript:
    > [] + {}
    "[object Object]"
    > {} + []
    0
    > {} + {}
    NaN
    > [] + []
    ""
    

    Which is also consistent given the ECMAscript standard, but not sensible by any stretch of the imagination. Dynamically-typed languages typically sacrifice being sensible for flexibility, and I typically treasure the former over the latter.

    Kambing on
    @TwitchTV, @Youtube: master-level zerg ladder/customs, commentary, and random miscellany.
  • Alistair HuttonAlistair Hutton Dr EdinburghRegistered User regular
    edited August 2014
    The standard style when using 'or' and 'and' with Boolable values is that one of them will be a constant whilst the other is a variable which avoids the confusion over what value will be returned by the expression.

    Alistair Hutton on
    I have a thoughtful and infrequently updated blog about games http://whatithinkaboutwhenithinkaboutgames.wordpress.com/

    I made a game, it has penguins in it. It's pay what you like on Gumroad.

    Currently Ebaying Nothing at all but I might do in the future.
  • RendRend Registered User regular
    edited August 2014
    I make a little face when the boolean or comparison operator is used on values which are not explicitly boolean. That is not what the boolean comparison operator is for, and it's simply confusing!

    This is ESPECIALLY true in languages like C++ when you are comparing values which are intended to be numbers, and you use the boolean value of the int as true or false. I would much rather see:
    if(a != 0)
    
    than...
    if(a)
    

    It's an ease of readability issue. If your thing has only two values, and they are obviously mapped to true/false 1/0, then boolean is right for the situation. People use it all the time because it's less space, but seriously? Screen space is NOT at a premium, and trading even a couple lines of code for readability (especially since most compilers will optimize the extra lines out anyway) is nearly always a HUGE win.

    Rend on
  • KambingKambing Registered User regular
    The standard style when using 'or' and 'and' with Boolable values is that one of them will be a (non-Falsey) constant whilst the other is a variable.

    Yup. The standard use is reasonable. However, I prefer that the language act reasonably with both standard and non-standard usage, because you can't anticipate which situation the programmer will find themselves in. And this is especially true in a dynamically-typed language where frequently errors are raised far (both spatially and temporally) from where the actual error occurred.

    @TwitchTV, @Youtube: master-level zerg ladder/customs, commentary, and random miscellany.
  • RendRend Registered User regular
    edited August 2014
    Also just to add, I should not need to go look up the fine print about how precisely an or statement is implemented in the language in order to make sense of a line of code: knowing what or means in general should be enough. The line "product(a, b or [None])" requires just that of me.

    Rend on
    Kambing
  • BarrakkethBarrakketh Registered User regular
    Kambing wrote: »
    EDIT: related, when both operands are false, then `or` is defined to not return False but b instead. This sort of makes sense for `or`, but by symmetry, `and` returns the a value by default. Then you get weird situations like this:
    >>> x = []
    >>> y = []
    >>> z = x and y    # Hrm, what is z referring to?
    >>> x.append(1)
    >>> y.append(2)
    >>> z
    [1]
    

    The definition of `or` in Python is consistent but not what I would call sensible.

    I don't think that is weird, but I also already knew that 'and' and 'or' are short-circuit operators in Python. 'z' couldn't have been 'y' since the latter was never evaluated. In the case of 'or' then 'y' would've been chosen.

    In practice, the only place I make use of 'or' like that is initializing variables. Due to how Python treats mutable default arguments (they are created when the function is defined, not called) you'll see this pattern used:
    def foo(a, b=None):
        b = b or []
    

    If you used "b=[]" in the argument list, the state of 'b' would persist across all invocations of 'foo'.

    Rollers are red, chargers are blue....omae wa mou shindeiru
    undergroundmonorail
  • Alistair HuttonAlistair Hutton Dr EdinburghRegistered User regular
    edited August 2014
    Rend wrote: »
    Also just to add, I should not need to go look up the fine print about how precisely an or statement is implemented in the language in order to make sense of a line of code: knowing what or means in general should be enough. The line "product(a, b or [None])" requires just that of me.

    But it's not a question of fine print. As an Ada programmer should I get annoyed that every other language uses short-circuit logical operators rather than having to make it explicit with 'or else'/'and then' like nature intended? No, I should learn the way of doing things in other langauges otherwise we're all stuck programming to the lowest common denominator of expressibility and that means we're all stuck writing Algol60.
    if 5 < x < 10:
        #Do thing
    

    Causes most other languages to crash on compilation, should it be verbotten to use that in Python as it would confuse those unfamiliar?

    Alistair Hutton on
    I have a thoughtful and infrequently updated blog about games http://whatithinkaboutwhenithinkaboutgames.wordpress.com/

    I made a game, it has penguins in it. It's pay what you like on Gumroad.

    Currently Ebaying Nothing at all but I might do in the future.
  • BarrakkethBarrakketh Registered User regular
    Rend wrote: »
    Also just to add, I should not need to go look up the fine print about how precisely an or statement is implemented in the language in order to make sense of a line of code: knowing what or means in general should be enough. The line "product(a, b or [None])" requires just that of me.
    You don't need to know exactly how it is implemented. It's described here in a truth table with short notes.

    Rollers are red, chargers are blue....omae wa mou shindeiru
  • KambingKambing Registered User regular
    Barrakketh wrote: »
    Kambing wrote: »
    EDIT: related, when both operands are false, then `or` is defined to not return False but b instead. This sort of makes sense for `or`, but by symmetry, `and` returns the a value by default. Then you get weird situations like this:
    >>> x = []
    >>> y = []
    >>> z = x and y    # Hrm, what is z referring to?
    >>> x.append(1)
    >>> y.append(2)
    >>> z
    [1]
    

    The definition of `or` in Python is consistent but not what I would call sensible.

    I don't think that is weird, but I also already knew that 'and' and 'or' are short-circuit operators in Python. 'z' couldn't have been 'y' since the latter was never evaluated. In the case of 'or' then 'y' would've been chosen.

    In practice, the only place I make use of 'or' like that is initializing variables. Due to how Python treats mutable default arguments (they are created when the function is defined, not called) you'll see this pattern used:
    def foo(a, b=None):
        b = b or []
    

    If you used "b=[]" in the argument list, the state of 'b' would persist across all invocations of 'foo'.

    It isn't the fact that `or` in Python is short-circuiting --- in most languages && and || are short-circuiting operators. It's the fact that, in Python, `or` (and `and`) produce non-boolean values which is very non-standard, especially from a types perspective as I pointed out above. The reason why that's the case is to have convenient syntax for "defaulting" values like what you described above. However, rather than lumping that into a non-standard definition of `or`, I'd rather see that be placed into some other operator (or function).

    @TwitchTV, @Youtube: master-level zerg ladder/customs, commentary, and random miscellany.
    EtheaRendiTunesIsEvil
  • InfidelInfidel Heretic Registered User regular
    Writing your code in a way that you have to understand Python is very Pythonic!

    But yeah, I always just try to figure out a language I am working with. There are always things that you should know and what you should expect to see.

    OrokosPA.png
    LD50
  • KambingKambing Registered User regular
    Barrakketh wrote: »
    Rend wrote: »
    Also just to add, I should not need to go look up the fine print about how precisely an or statement is implemented in the language in order to make sense of a line of code: knowing what or means in general should be enough. The line "product(a, b or [None])" requires just that of me.
    You don't need to know exactly how it is implemented. It's described here in a truth table with short notes.

    Eh. That is how it is implemented. That's exactly the piece of the documentation you have to find to answer Rend's question: oh wait, `or` produces a non-boolean value? What value does it produce then?.

    @TwitchTV, @Youtube: master-level zerg ladder/customs, commentary, and random miscellany.
    Rend
  • gavindelgavindel The reason all your software is brokenRegistered User regular
    Got an offer. Such salary, much benefit package, wow.

    Angels, innovations, and the hubris of tiny things: my book now free on Royal Road! Seraphim
    admanbKambingIncindiumEchoEtheaBarrakkethInfidelDisruptedCapitalistMvrckmightyjongyoRendecco the dolphinurahonkyDelmainLD50KakodaimonosPolaritieMNC Doveran_altTofystedeth
  • EtheaEthea Registered User regular
    gavindel wrote: »
    Got an offer. Such salary, much benefit package, wow.

    Make sure you graduate, instead of accepting a job that requires you to drop out.

    MvrckmightyjongyourahonkyDelmainan_alt
  • GnomeTankGnomeTank What the what? Portland, OregonRegistered User regular
    Essentially Python's 'or' acts as both an OR and a coalescing operator, and it's on my list of reasons I hate Python. It's low on the list mind you, but it's on the list.

    Sagroth wrote: »
    Oh c'mon FyreWulff, no one's gonna pay to visit Uranus.
    Steam: Brainling, XBL / PSN: GnomeTank, NintendoID: Brainling, FF14: Zillius Rosh SFV: Brainling
  • KambingKambing Registered User regular
    edited August 2014
    Rend wrote: »
    Also just to add, I should not need to go look up the fine print about how precisely an or statement is implemented in the language in order to make sense of a line of code: knowing what or means in general should be enough. The line "product(a, b or [None])" requires just that of me.

    But it's not a question of fine print. As an Ada programmer should I get annoyed that every other language uses short-circuit logical operators rather than having to make it explicit with 'or else'/'and then' like nature intended? No, I should learn the way of doing things in other langauges otherwise we're all stuck programming to the lowest common denominator of expressibility and that means we're all stuck writing Algol60.
    if 5 < x < 10:
        #Do thing
    

    Causes most other languages to crash on compilation, should it be verbotten to use that in Python as it would confuse those unfamiliar?

    No. Of course, when in Rome, do what the Romans do. But certainly, just becomes the Romans do something in their home, it isn't an ideal thing to do.

    Python, in particular, favors convenience over regularity in its semantics. I personally don't like that about the language from both a designer's perspective --- irregularity leads to hard-to-diagnose errors --- and an educator's perspective --- irregularity means more "corners" that a student needs to reason about.

    Comparison chaining is one of those conveniences (albeit less offensive because it's more difficult to produce "poisonous" errors from them). In most languages, comparisons are a binary operator so 5 < x < 10 is ill-typed because precedence dictates that we have (5 < x) < 10 and (5 < x) has type bool and 10 is type int which are incomparable things.

    In Python, comparisons are not strictly binary. Indeed you can have chains of them, e.g.,
    >>> x = 3
    >>> y = 7
    >>> 0 <= x <= y <= 10
    True
    

    Which is very convenient because this is how we'd normally write comparisons. But because of regularity of syntax, we can also write expressions such as:
    >>> 0 <= y >= x <= 10
    True
    >>> 0 <= y >= x <= 3
    True
    

    Which does not obey our common sense understanding of how comparison chaining works, at least when we write such things on paper --- y = 7 which is not <= 3 so surely the expression is False. By trial-and-error or reading the standard (https://docs.python.org/2/reference/expressions.html#not-in), you can derive what is actually happening:
    e1 op1 e2 op2 ... opn em
    
    ~equivalent to~
    
    (e1 op1 e2) and (e2 op2 e3) and ... (em-1 opn em)
    

    Which explains why y <= 3 is not checked. To do "the thing you might expect" requires more mathematical smarts (systems-of-constraints solving) than a compiler writer is willing to invest. And so we reach a compromise in language design regularity versus "convenience" where many languages opt for the former (regularity) and Python opts for the latter (convenience). "Convenience" is in quotes because while such semantics enable some common case comparison chaining, they are not general enough to handle all of the cases that the language admits (in the way that you expect, at least).

    (EDIT: there's also the whole bit about side-effects in the language as well. Note that it seems like the desugared form of a comparison chain requires that we evaluate each of e2 ... em-1 twice. If these expressions contained side-effects, then those side-effects would be evaluated twice. Thankfully, the Python standard notes that each expression is explicitly only evaluated once in the usual short-circuiting fashion even though the expanded form suggests otherwise.)

    Kambing on
    @TwitchTV, @Youtube: master-level zerg ladder/customs, commentary, and random miscellany.
This discussion has been closed.