3 ms·
> and smells like a goto. What about while/break, for/break, try/except, etc doesn't "smell like a goto"? Isn't that the whole point of these sophisticated con
by shawnz 8y ago
> and smells like a goto.
What about while/break, for/break, try/except, etc doesn't "smell like a goto"? Isn't that the whole point of these sophisticated constructs, to serve as more rigorous replacements for "goto"?
- contravariant 8y agoSure, and break/continue etc. should be discouraged for that precise reason. I don't quite see try/except/finally as a goto, since I'm not sure how to make one that behaves that way. However IMO the best 'rigorous' model of programs is maintaining pre and post conditions. Escaping early when the post-condition is satisfied is compatible with this model (like with e.g. return/break/continue). Escaping in two different ways is not. If you really need to handle exceptional cases where you need to escape a loop differently then exceptions are the better option IMHO, these also have a fairly rigorous definition in terms of Monads. Obviously if actual Monads (which in the case of python would be containers / generators) are an option they should be preferred.
- shawnz 8y ago> I don't quite see try/except/finally as a goto, since I'm not sure how to make one that behaves that way. I suggested try/except because goto is very commonly used to provide similar behaviour in C where there are no exceptions. > break/continue etc. should be discouraged for that precise reason ... the best 'rigorous' model of programs is maintaining pre and post conditions ... Obviously if actual Monads are an option they should be preferred. But why? Do you have any evidence that this leads to better/more robust/easier to understand code in practice?
- contravariant 8y agoDoes personal experience count? (note also that I indicated that ultimately all of this is just my opinion). Personally I find I mostly end up creating bugs when I don't have a clear enough image of what the proper pre-condition to a loop should be and what its post-condition should be. I therefore believe that code that by its very structure can't easily be assigned pre/post conditions would make things quite difficult. Post-conditions also tend to make it easier to reason that the code is correct (provided they are documented). As for the Monad quote, well it's use is somewhat limited in Python, however returning a 'trivial' result rather than an exception usually ends up being easier to work with. Which is appropriate varies though, and in Python there's not much reason to avoid exceptions for performance reasons anyway.
- kazinator 8y ago> Sure, and break/continue etc. should be discouraged for that precise reason. If you naively banish break and continue, but then the programmer has to work around your banishment by adding one more state variable, and assigning to that variable, you have not gained anything. You've pushed down a bulge in the carpet, only to have it pop up elsewhere. Assignment and goto are bedfellows, which is why purely functional programming banishes both. (Goto, at its essence, is in fact an assignment to the program counter.)
- contravariant 8y agoNote I said discouraged not banished.
- joshuamorton 8y agoGenerally speaking, things that use break can be cleaned up by using python's `any` or `all` constructs over a slightly reworded loop. This isn't always true, but handles most of the common cases. I don't think that I've yet come across a use of break/continue that can't be pretty cleanly refactored into a helper method like def my_filter(items): for x in items: if cond(x): yield x for x in my_filter(base_list): process(x) This ends up being pretty clean and describes exactly what/why you're filtering things, plus as the conditions change you can test things individually.
- maxbond 8y agoOne might also consider using something like `map(process, filter(cond, items))`
- yorwba 8y ago> However IMO the best 'rigorous' model of programs is maintaining pre and post conditions. Escaping early when the post-condition is satisfied is compatible with this model (like with e.g. return/break/continue). Escaping in two different ways is not. Escaping in two different ways really isn't a problem for that kind of analysis. You just have to make sure that the post-condition is satisfied at each exit. For/else is actually a great construct for that, where the else branch is used to achieve the same post-condition as after a break, which would be more difficult if there were no difference between the loop exiting with a break or by exhausting the iterator.