Skip to main content
28 events
when toggle format what by license comment
Feb 13, 2023 at 18:51 comment added cHao @mtraceur: You can't "structure" preemption, not using a standard definition for both of those words. It's not just that the concept is unknown, it's that logically, it's like having a rectangular circle. One of those definitions has to give.
Feb 13, 2023 at 17:15 comment added mtraceur @cHao If you are unable to know concept exists without someone having already named it and spread it through the culture before you encountered it, I'm sorry but that's a bigger problem I don't have the time or motivation to help with. Cooperative multitasking is part of what I call structured preemption. Or to be more precise, cooperative multitasking is the absence of any preemption, but if we set out to structure preemption as we did jumps and concurrency, the result ends up looking a lot like cooperative multitasking up to a point. Anyway I'm done here.
Feb 13, 2023 at 16:11 comment added cHao @mtraceur: I didn't mention structured preemption because there's no such thing. That's just cooperative multitasking. The very idea of preemption is that a process has little to no control over when control gets snatched away from it, which is the opposite of "structured" from the process's POV.
Feb 13, 2023 at 15:58 comment added cHao @mtraceur: I think the only time it's good to confuse a rule with its purpose is if you want to check a box to satisfy obstructionist bureaucrats. SESE in most languages these days is a stupid rule and should not be adhered to without a damn good reason, and the top answer basically echoes that assessment.
Feb 13, 2023 at 15:54 comment added mtraceur @cHao Re: other point: everything bad about explicit threading with afterthought control clawbacks just boils down to what I said. The ability to start a process/thread/coroutine/task explicitly rather than implicitly is largely irrelevant, but the thing that's good about concurrent execution being subordinate and under control of the caller is precisely that it allows you to call a function and trust that you don't need to know if it internally uses concurrency. Also (we both forgot to mention) structured preemption: yielding to preemption only at designated visible-in-the-code spots.
Feb 13, 2023 at 15:53 comment added mtraceur @cHao I think the only time it's good to value a rule over its purpose is if you want to build a world that favors obstructionist bureaucrats and letter-of-the-rule abusers, so I don't know why this is a hill you want to fight for. Anyway, re: "most interpretations of SESE" - perhaps a glance at the top voted answer on this very question is in order.
Feb 13, 2023 at 15:50 comment added cHao @mtraceur: A guard clause does, in fact, violate most interpretations of SESE. The goals are irrelevant; the principle isn't defined by the goal, but by the specific way of accomplishing that goal.
Feb 13, 2023 at 15:41 comment added mtraceur @cHao If by "defined exit point" you mean defined exit destination, sure. Because for example an early-return guard clause doesn't violate SESE in any way that matters to the goals that SESE's existence is entirely predicated on. So even if you argue that the essence of a purpose-serving rule is the rule implied by the words of its memorable name rather than its purpose, the "single exit" was always more about a single invocation having just one possible return/exit jump target.
Feb 13, 2023 at 14:47 comment added cHao @mtraceur: The essence of SESE is right there in the name. Sequential routines have a defined entry point and exit point, and you're not to bypass either. It's so that the structure is easier to reason about, and is an obvious way to make it so, but is not the only way, as evidenced by the idea of guard clauses, generators, coroutines, etc being a thing. Concurrency's big slip-up was initially preferring explicit threading and then providing ways to claw back control, rather than the more limited async model of subordinate tasks promising to return a value eventually.
Feb 10, 2023 at 20:48 comment added mtraceur @cHao yep, though the essence of SESE is not the number of entry points and exit destinations - it's if execution is forced to follow structure we can easily reason about and see from the source. A yield or await is still fine because when you call/resume a generator/coroutine at a spot, the yield/resolve/exception will come back to that spot if it comes back at all. Concurrency's big structured programming slip up was allowing functions to return before all their concurrent branches are done or cancelled. (Which is like a malloc without a free and like a longjmp without a setjmp.)
Feb 10, 2023 at 19:47 comment added mtraceur @DonalFellows just five years after your comment, people started to remember structured programming and apply those same ideas to concurrency just as we applied it to jumps back in the day. See "Structured Concurrency" by Sustrik (main ZeroMQ author, who also wrote libdill as maybe the first structured concurrency implementation) and "Go Statement Considered Harmful" by Smith (main author of the Python library Trio and Python core contributor if I remember right).
Jun 13, 2020 at 1:34 history edited Basil Bourque CC BY-SA 4.0
Linked to Wikipedia and other resources.
Oct 26, 2012 at 15:24 comment added cHao @DonalFellows: Part? :) True coroutines would seem to pretty much turn SESE on its ear. Generators, not quite so much, as they don't choose where to "yield" to; although on a conceptual level there's still a number of "entry points", most languages that use generators aren't able to actually jump straight to those entry points. Generators in those languages are really just hidden state machines.
Nov 11, 2011 at 23:54 comment added Donal Fellows I find it curious how coroutines (and generators) are making something of a comeback these past few years, as they definitely have the ability to violate part of SESE, albeit in a limited sense.
Nov 11, 2011 at 16:17 history made wiki Post Made Community Wiki by Eugene - AmberPixels
Nov 9, 2011 at 22:05 comment added Shog9 @John, you seem to be trying to answer the question without actually answering it. It's a fine reading list, but you've neither quoted nor paraphrased anything to justify your claim that this essay and book have anything to say about the asker's concern. Indeed, outside of comments you've said nothing substantial about the question whatsoever. Consider expanding this answer.
Nov 9, 2011 at 20:33 comment added John R. Strohm From the original question: "Where did this notion of "one return only" come from, and why do people adhere to it rigidly?" In other words, the original question is "Where did Single Entry/Single Exit come from?", and the answer is that it came from the Structured Programming movement of the early 1970s.
Nov 9, 2011 at 19:58 comment added John R. Strohm @missingno: Thank you for the correction. It has been many years since I read the paper, and I was not aware that Bohm & Jacopini's paper actually preceded it.
Nov 9, 2011 at 18:36 comment added Flexo - Save the data dump @JohnR.Strohm - if the argument is that writing return twice in one function will cause it to multiply across the code base then I think it's flawed. Just because you wrote it once in one function doesn't mean you'll unwilling have to write it a second time, in another function. That is unless the construct proved usefully expressive enough as to make it desirable, but "usefully expressive" is a whole world apart from "parasitic infestation". If the code base is so tightly coupled that it does cause this then I'd start to worry about the elephant in the room first.
Nov 9, 2011 at 18:35 comment added jalf What does this have to do with the question? Yes, Dijkstra's work eventually led to SESE languages, and so what? So did Babbage's work. And perhaps you should re-read the paper if you think it says anything about having multiple exit points in a function. Because it doesn't.
Nov 9, 2011 at 18:22 comment added hugomg From the last paragraph of "Goto Statement considered harmful": "in [2] Guiseppe Jacopini seems to have proved the (logical) superfluousness of the go to statement. The exercise to translate an arbitrary flow diagram more or less mechanically into a jump-less one, however, is not to be recommended. Then the resulting flow diagram cannot be expected to be more transparent than the original one."
Nov 9, 2011 at 17:50 comment added cHao Heavy use of break, continue, return and goto can obfuscate. But they have their place, and when used decently (ie: when they are appropriate), they increase readability by pruning the decision tree. The argument was against the unbridled use of goto, not against its use ever -- break/continue, being restricted, are outside of the argument's scope. But even Dijksta would have to admit that abolishing goto entirely is unrealistic -- and Wirth (who published and even named that article, and took it to heart) did admit as much when he added a goto to pretty much every language he designed.
Nov 9, 2011 at 16:17 comment added John R. Strohm @cHao: What Dijkstra observed was that GOTOs tended to proliferate ("multiply like cockroaches" might be a better analogy) in code, and multiple GOTOs invariably obscured the intent of the code. This was before the "structured" control structures were common, and before Bohm & Jacopini's [Google is your FRIEND!] formal proof that the structured control structures were all you needed. Today, heavy use of "break", "continue", and "return" in the middle of a random mass of code are just as effective at obfuscating the code's intent as GOTO was in the early days.
Nov 9, 2011 at 15:41 comment added cHao The article was also written in the days when goto could literally go anywhere, like right into some random point in another function, bypassing any notion of procedures, functions, a call stack, etc. No sane language permits that these days with a straight goto. C's setjmp/longjmp is the only semi-exceptional case i'm aware of, and even that requires cooperation from both ends. (Semi-ironic that i used the word "exceptional" there, though, considering that exceptions do almost the same thing...) Basically, the article discourages a practice that's long dead.
Nov 9, 2011 at 15:34 comment added FUZxxl @user606723 No. In most architectures, the code to return from a function is as simple as writing leave; ret (x86) or pop 1,0 (MMIX). In most cases, that is much simpler than jumping to the exit point.
Nov 9, 2011 at 15:21 comment added user606723 The article was written in days before C when GOTO's were used heavily. They aren't the enemy, but this answer is definitely correct. A return statement thats not at the end of a function is effectively a goto.
Nov 9, 2011 at 14:22 history edited Mark Booth CC BY-SA 3.0
Added link for EWD215.
Nov 9, 2011 at 13:46 history answered John R. Strohm CC BY-SA 3.0