15 ms·
Loop Exits and Structured Programming: Reopening the Debate (1995) [pdf]
- GrumpyNl 9y agoSoftware, what its all about: assignments if and while loops
- tuukkah 9y agoOnly imperative programming though. (Functional programming is the opposite.)
- eru 9y agoAnd even in imperative programming, you don't need the loops. At least not as a built-in.
- mort96 9y agoYou don't need ifs either, just conditional goto.
- eru 9y agoYou don't need ifs nor conditional jumps. Functional calls are truly enough. I can show you how it's done, if you want to see it. Thus you can implement 'if' as a user defined function in eg Haskell. (But I'd advise against the totally if-less style. Pattern matching is just too convenient. (And ifs are just a special case of pattern matching on booleans.)) Pure lambda calculus doesn't I have ifs. If you want to go truly crazy, check out SKI calculus. It doesn't even have lambda abstraction.
- GrumpyNl 9y agoThe basics still stands, doesnt matter how you call it or do it different.
- eru 9y agoSorry, what do you mean? If I may guess: you want to make gotos central? That only holds for compiling to von-Neumann machines. Some other computational structures might not even have instruction pointers to move around.
- awinter-py 9y agoThis is relevant. There are lots of real-life errors that come out of these errors and the worse mistakes people make trying to work around control flow (goto fail?). I desperately want a 'break break' command. Not a label break, which is painful to work with, but an instruction to break the current loop and the outer loop.
- danthemanvsqz 9y agoWrap the double loop in a function/method and return from the inner loop.
- Animats 9y agoThat works well except when you're in a language where you can't nest functions and need data from the outer scope. C is like that. Rust really likes to bail out of functions when something goes wrong. That's what "try!()" does. Allowing multiple exits from a loop is no longer controversial. Multiple entries into a loop are still considered undesirable. From a proof of correctness standpoint, the topology requirement is that there be some single place within the loop through which control must pass. That's where the proof inductive step takes place, and where you prove loop termination by showing that some measure is decreasing. Restrictions stricter than that are more stylistic than formal.
- eru 9y agoIn GCC's C you can nest functions. (But that's not portable.)
- graycat 9y agoAh, you seem to be talking about having the source code of function X inside the source code of function Y and, then, the names known in function Y are also known in function X unless declared again within function X. I LIKE that! That's what PL/I has. Once I got a phone interview from Google. An early question was, "What is your favorite programming language?" Sure, right away, PL/I! Opps, (from a movie) "way wrong answer!". Apparently the only right answer was C++. Gee, I didn't want to lie. Besides, to me saying C++ instead of PL/I should cause me to lose a full letter grade! So, PL/I has descendancy, static and dynamic. The static version is from the nesting in the static source code. The dyanmic version is from functions, subroutines, etc. that have been called (are active) but have yet to return. Then with such descendancy and entry variables, can get some interesting situations, design patterns! I did that once and avoided a total mess in the IBM AI language KnowledgeTool!
- woliveirajr 9y agoI love all those "goto" disguised as any kind of flow controls. Because goto is devil, but give it another name and another smell and, voilà!, it becomes beautiful.
- Symmetry 9y agoAt a hardware level all control flow is made up of gotos. But by writing them as 'for' or 'break' or 'if' in our programs we make them easier to read by letting the reader know that the jump is restricted in certain ways.
- nickpsecurity 9y agoNah, hardware is more like dataflow or flow-based programming. Maybe functional programming, too. Goto is jumping to arbitrary, imperative code in RAM with an address and no regard for current state. There's possibly something in hardware like it but default stuff I saw in books were more like FSM model focused on data flows.
- Symmetry 9y agoYou're right that I should have said "At the level of the software as understood by the hardware" or something instead.
- woliveirajr 9y agoYes, I know :) . Having learnt to program some microprocessors, I love how everything is evaluated in terms of jump-if-zero, jump-if-not-zero. Well, even some cracks to copy-protection from older games (dating myself here) was just a single change from a hex 74 to a hex 75 somewhere in the code. And, sometimes, even in small programs, knowing where you are after some jumps is a messy thing. I just don't have all that rant against jumps (or goto's). I know where they live, what they eat, when they are useful and when are not. :)
- sigjuice 9y agoI encountered one of these beautiful things you mention not too long ago. void foo() { do { for (...) { if (...) { break; } } if (...) { ... if (...) { ... break; } } /* even more nested loops and conditionals with break sprinkled all over */ } while (0); ... } PS: IMHO this code goes too far with the "goto considered harmful" philosophy. The "while (0)" is serving the purpose of a label. An explicit label instead would be more readable, IMHO.
- eru 9y agoJust use functions calls already. Modern languages and compilers / interpreters have gotten good enough (at least the ones that care), that there's no need to bless a small set of control structures by being special-purpose built-in.
- graycat 9y agoAh, the OP probably has better ideas, but I know what I like! E.g.: Do Forever If A Then Leave If B Then Call X If C Then Iterate Call Y Leave End Ah, that style of loop writing may cause some purists to scream bloody murder!
- mcguire 9y agoI used to know a guy who used a loop structure something like that. For every loop. One of threw weirdest things I have ever seen. Some people seem determined to cause facial tics in everyone they meet.
- graycat 9y ago> Some people seem determined to cause facial tics in everyone they meet. Maybe so, but not me. So, what is the justification for the Do Forever loop above? First, I illustrate that we can want to exit the loop for (A) whatever conditions are discovered in the loop and (B) at any point in the loop and not just the beginning or end which is the usual situation, e.g., for Do i = 1, 10 or Do While X If I write Do I = 1, n does the loop logic deciding when to exit ever form n + 1? If n is the largest integer, then maybe we'd like to know. With Do Forever we may have more control, enough more to avoid forming n + 1 unless we really want to. Second, when I start writing a loop, I may not have yet worked out all the details or how to get what I do want just from some Do While X Etc. So, I just start the loop with Do Forever and work out the exit conditions as I keep typing. Third, with Do Forever can often get the results of using a GOTO without actually doing so. So, if the target of the GOTO would be just after the loop End, then can get there within the loop with just a Leave. Of course, when write such a loop with Do Forever, should write some comments that explain (A) what the purpose of the loop is and (B) how the code in the loop does accomplish that purpose. That is, should not force someone reading the code to guess at (A) and confirm (B). For proofs of correctness based on the usual mathematical induction, I'm not convinced that loops with Do Forever are fundamentally more difficult. > Some people seem determined to cause facial tics in everyone they meet. Maybe so, but not me.
- ajarmst 9y agoWhen I teach this stuff, I try to distinguish between (1) Returning/Exiting/Excepting because of a legitimate error condition (2) Returning/Breaking early because there's either no work to do or something necessary to do the work is absent/unavailable (the latter often turns into a case of (1) (3) Returning/Breaking/Continuing early because I've discovered the work is done for either all iterations or this particular iteration, and the remainder of the function/method/loop is pointless cycling. (Often added during optimization, sometimes added too early). (4) Returning/breaking/GOTOing because I've gotten confused and want to go to a place in the code that makes more sense to me. This is the only that's actually a problem and should be railed against. Unfortunately, it's way more common than it really should be in beginners' programs. I think GOTO got an early bad rap---try writing non-trivial machine code or assembler without liberal use of goto, and many very useful techniques in debugging are basically informed application of goto---because of what I call the "pull the ejection handle" approach to getting into trouble trying to code an algorithm you dont really understand.
- cabaalis 9y ago1. Does the code do what it's supposed to do, without crashing or causing unwanted side-effects? 2. Is the code relatively readable by someone unfamiliar with the problem? If 1 && 2 then stop tearing your robes like Pharisees and go solve another problem.
- glangdale 9y agoGoto gets a bad rap, and I have seen many programs where an explicit goto, to a label that is descriptive, is way clearer (and less brittle under reorganization) than a 'structured' break or continue - or some spaghetti of booleans (while (!done) ... ). It's clearly very easy to write bad code in many ways, but (very) judicious use of goto is occasionally far clearer than assuming goto is always bad and building something complex out of bools, break and continue. It seems to be a test of common sense: if goto is clearer than the alternative, use goto.
- mcguire 9y agoIn one paper on the structured programming issue, Don Knuth has a beautiful axiomatization of goto by Tony Hoare: https://maniagnosis.crsr.net/2011/11/link-o-day-donald-knuth-tony-hoare-and.html https://maniagnosis.crsr.net/2011/11/link-o-day-donald-knuth...
- dbaupp 9y agoYour specific example sounds like the kind of thing addressed by more powerful structure: labelled break, as appears in Java, JS, Rust and Swift (among others, I'm sure). Of course, thinking about labelled break is just dreaming when required/choosing to work in a language without it.
- nickpsecurity 9y agoIt's why some of us built 4GL's, DSL's, preprocessors, and so on that added stuff to such languages but extracted to purely that language. Mine was a BASIC with macros translated to C w/ safety checks.
- userbinator 9y agoUnfortunately, in my experience the abuse of labelled breaks to avoid gotos tends to be even worse than abuse of regular breaks, since the label no longer shows immediately where the flow goes; it only labels the start of the block, when what you really want to see is the end.
- 9y ago
- fmatthew5876 9y agoIts really not that hard. Instead of blindly following rules someone else wrote, just read the code. Is it easy to follow? How many details do you have to juggle in your head? How many indented scopes are there? How much state is there? Can you mostly read it from top to bottom, or do you constantly have to jump around the file? If someone unfamiliar with the code (maybe you in 3 months) needs to make a change, how easy would it be for them to overlook some important detail and mess it up? Best practices usually apply in general, but the smart person who coined them cannot know all possible situations and the parrots who blindly repeat them don't know what they're talking about. Think for yourself, know your tools, and use them effectively to make your code as simple as possible.