<p>The compiler enforces the rules, everything else is a guideline.  It is a bit like ending a sentence with a preposition, about which Winston Churchill said:</p>
<blockquote>
<p>“This is the sort of [English] up with which I will not put.”</p>
</blockquote>
<p>In order to satisfy that <em>guideline</em> of English usage, sometimes we would end up with an extremely awkward sentence construction.  So being a good writer/orator means knowing when to be flexible about the guidelines.  Programming is no different.  Avoid early returns (if that is the local culture) unless the code ends up being too cryptic in an effort to avoid them.  We should encourage the student to develop their judgement about code quality, rather than blindly enforcing guidelines.</p>

CC BY-SA 4.0
2022-05-01T13:47:33.747Z
2022-05-01T13:47:33.747Z
Dikran Marsupial
<p>Forcing the students not to return early is bad, and forcing them to do so is bad as well. See, the issue of whether or not one should use early returns is not only superficial, but also primarily opinion-based, as both approaches are valid considering the individual circumstances. A teacher should not enter the overly authoritative role and impose their subjective stylistic preferences on students. From my own perspective, which is the one of a student, I had encountered a lot of teachers who have been presenting subjective opinions as objective standards, and personal whims as supposedly written gospel. All it succeeded in achieving was confusing all the students from the beginning, and setting all of them for numerous surprising awakenings once a teacher's God-given truth turned out to be a matter of taste, and thus nonsense.</p>

CC BY-SA 4.0
2022-05-19T21:14:46.147Z
I often present these sorts of preferences as "Most of you don't yet have a philosophy about how to approach __.  I am going to share *my* philosophy with you in this course, and I will also share with you why I think it is so valuable. I ask you to abide by it here. Perhaps after you've lived with it, you'll find value in my approach and wish to take it with you. However, if you later decide that this approach isn't for you, that's fine, too. Believe me, I won't be offended. At that point, at least you'll definitely understand *what* you're rejecting, and that is also a benefit."
Ben I.
CC BY-SA 4.0
2022-05-20T00:59:23.263Z
I've upvoted for the sentiment. But do realize what a deep problem you're unearthing. Newell&Simon described CS as a *Science of the Artificial*. Which implies **There are no objective truths here.**  So then what/how do we teachers teach?
Rushi
CC BY-SA 4.0
2022-05-20T02:08:39.623Z
@Rusi I'm not sure what you mean.  There's plenty of objective stuff on the mathier side of the field. Information theory certainly seems pretty objective.  There are strict limits on how compressed any information can be encoded.  The halting problem also seems pretty objective.
Ben I.
CC BY-SA 4.0
2022-05-20T02:54:29.460Z
@BenI. The short (& not v useful) answer is things like https://arxiv.org/pdf/math/0209332. And
 http://aleteya.cs.buap.mx/~jlavalle/papers/wegner/strong-cct.pdf. But I hasten to add: I'm as uneasy quoting these (without loud grunts!) as I would be saying *Drinking detergent cures covid*. The more relevant arguments are considerably longer. And we can reserve it for chat (if you wish). For here just this much: Your position *State your philosophy underneath your facts* has serious downsides. Students don't typically want high truth but high grades  — not cseducator notwithstanding 
Rushi
CC BY-SA 4.0
2022-05-20T14:49:55.017Z
I sympathize with your point of view, but ask yourself what the other options are. Either your teacher imposes no style at all, or exposes you to *all* styles. Given that as a learner you are unlikely to develop a good style from scratch, I would say that learning at least one consistent style from a teacher is preferable.
Victor Eijkhout
CC BY-SA 4.0
2022-05-19T20:06:02.767Z
2022-05-19T20:06:02.767Z
NOT CSEducator
<p>I propose that the correct answer is to keep doing what you're doing, by teaching the techniques that you're currently teaching.  Both of you.</p>

<p>I was taught with the approach you use.  When I was first exposed to the other approach, I didn't much like it.  But with an open mind, I learned that the approach used by the other instructor is useful for some analysis processes.  Most especially this refers to some particularly older "source code analysis" software tools, but there may be some ongoing benefit to that other style too.  As I didn't have experience with the practice of using those specific auditing processes, I'm not in the best position to judge whether the benefits outweigh the pains of constraints.</p>

<p>So, have students be taught both methods.</p>

<p>Maybe students won't like being coerced into being graded on how well they use one method, only to be later graded in another class based on how well they accomplish coding using the other style.  The transition may be unpleasant.  Tough.  That's great.</p>

<p>It is good for students to be prepared for the workforce, and many may benefit greatly from learning that an expected style might not match whatever their personal preference is.  If they are allowed to get locked into one style, that may cause challenges in the future when they transition into their first employer, or transition between companies, or even transitioning between different departments of an organization that may have different policies for different departments.  Getting the students uncomfortable if they don't adapt may be better for them to experience now.</p>

<p>If having different requirements leads to them being uncomfortable, tell them that different employers may expect different things, and even different projects (e.g., different open source projects) that they may want to become a part of during their off-time.  So may different instructors.  They are welcome to use whatever approach they want for their own personal hobby projects that they are in charge of, but when other people are in charge, then cooperation can be oodles more important than advantages of a particular style.</p>

<p>So, no, my advice here is: don't give them a choice.  Make 'em adapt.</p>

CC BY-SA 3.0
2018-03-11T02:38:54.760Z
I am reminded of [One's Final Words from ST:Voy (YouTube Video)](https://www.youtube.com/watch?v=yGOYjj2JCN0&t=53s)  Though hopefully not at all for the same reason, if the student gives the same response as what we see from Seven of Nine Tertiary Adjunct of Unimatrix Zero One over the next ten seconds, that effect just might be precisely the best that you can hope for...
TOOGAM
CC BY-SA 3.0
2018-03-11T02:38:11.030Z
2018-03-11T02:38:11.030Z
TOOGAM
<p>Teach your students about the <code>return</code> early philosophy. Teach your students about the single <code>return</code> philosophy. Tell them this debate is not settled. Explain to them that different software development teams have different opinions and different standards, and that it's important for them to have both these tools in their toolbox for their jobs.</p>

<p>Explain the risks of each:</p>

<ul>
<li>Return early can result in mistakes where the function is modified so that something that should happen unconditionally doesn't or only happens under the wrong conditions.</li>
<li>Single return carries the risk that a change that should happen only conditionally might be accidentally made unconditionally or under the wrong conditions.</li>
</ul>

<p>Both of these risks are greater if the function is particularly long or complex or if the change is a state modification (e.g., database commit). Explain to them that this is a good reason to prefer shorter functions and stateless code when feasible. The important thing is to make the code easier to understand and easier to modify without making mistakes.</p>

<p>Now let them decide when they write their own code. Then give them an assignment to modify their code that carries these risks and let them try it out.</p>

<p>Also use it as a chance to caution them about being dogmatic in software design. Writing software is full of things where there's no clear cut, <em>always</em> right answer. The right choice very often depends on the specific situation and sometimes even the culture of a particular team.</p>

CC BY-SA 3.0
2018-03-10T05:21:01.093Z
+1 A function that won't fit in one screen of text is usually too long and needs to be broken up (except when it isn't)
pojo-guy
CC BY-SA 3.0
2018-03-12T13:52:30.793Z
It's also important to teach them about coding standards, and that those standards will probably dictate which one they must use.
Doctor Jones
CC BY-SA 3.0
2018-03-12T15:30:41.870Z
@DoctorJones I wouldn't say "probably," as a lot of shops won't have something like this formally documented. ;) And unless you're working on something that's life and death, a standard to this level of detail is probably too heavy weight. But yes, they should be aware that it's possible.
jpmc26
CC BY-SA 3.0
2018-03-10T00:11:15.673Z
2018-03-10T00:26:12.280Z
2018-03-10T00:26:12.280Z
jpmc26
<p>Actually returning early should be the norm. Return as soon as you can. There are at least two reasons for this, of which the first, efficiency, is the least important. But if you return early then needless statements won't be executed. Nor will you need to devise some special code to get to the end just so that you can return. </p>

<p>However, the biggest and most important reason for returning early is that the programmer can put a limit on what she/he needs to retain mentally about the state of the computation. This is especially helpful in a sequential if situation. There is actually an Elementary Pattern about this ("Return, not else") that says that if you know what should be returned at the end of an if block, don't use an else, but instead end the block with the return. The reader/writer/updater then gets to ignore the previous state and start over in their thinking process. </p>

<p>If you return only at the end, say "return result;" then you have to track all changes to <em>result</em> that might occur anywhere in the function/method. You have to understand it "as a whole" rather than incrementally. But the reading itself is normally sequential and incremental. </p>

<p>Of course if you always write three statement methods, this won't occur, but few have the discipline to really do that. Sadly, some programmers can't understand their own code when it contains very many nested structures and tests. </p>

<p>I'll also note that this is somewhat related to the idea that we generally try to avoid global variables in programming. Too much extraneous information can impinge on understanding. Being able to comprehend a program "one block at a time" without reference to others, even containing blocks, is a big advantage. </p>

<hr>

<p>Caveat. Of course, the code should be as clear as possible. If returning late makes it clearer, I wouldn't <em>forbid</em> it. But I think that is seldom the case. Forbidding early returns, however, is counterproductive. </p>

CC BY-SA 3.0
2018-03-09T23:16:51.510Z
I think that caveat is more important than calling it a "caveat" may suggest. I'm of the opinion that clear and understandable code is priority #1 (well, maybe #2 after _working_ code), and all other rules can be bent to that aim. But if you do want to have a general principle about early returns, I definitely agree that allowing and even encouraging them seems like a better choice than forbidding them, for exactly the reasons you describe.
David Z
CC BY-SA 3.0
2018-03-10T01:27:38.607Z
I'd also like to add a caveat -- this answer makes a lot of sense in a high school context, where the language is probably high-level (Python, Java, etc.) with managed memory. In lower-level languages (e.g., C), returning late may make for [much cleaner and more readable code](https://stackoverflow.com/a/245761/5003848).
tonysdg
CC BY-SA 3.0
2018-03-10T01:36:30.670Z
@tonysdg, I don't find the code you link to very compelling. I can make it much cleaner and more understandable with no goto statements at all. For example, within the limits of formatting here, a part of it could be: `if (!doB()) {undoB(); undoA(); return;}` (undoing both B and A)
Buffy
CC BY-SA 3.0
2018-03-10T01:50:44.337Z
@Buffy: The second comment on that answer says the very same thing actually :) I guess I personally find the format in that link to be very clean -- it reminds me of unwinding a stack -- but I see your point. I'll also point to [this answer](https://stackoverflow.com/questions/24451/is-it-ever-advantageous-to-use-goto-in-a-language-that-supports-loops-and-func/24476#24476) on a separate question -- the answer and its comments have (IMO) thought-provoking points about the pros and cons of various forms of control flow (`return` and `goto` included). Probably out of scope for high school tho.
tonysdg
CC BY-SA 3.0
2018-03-10T05:20:15.283Z
Modern optimizers are pretty sharp about implementing return early even when you don't do it in your code. The efficiency argument is not as strong as it was when I was learning.
pojo-guy
CC BY-SA 3.0
2018-03-11T20:16:37.957Z
I was taught never to return early.  Then in javascript I realized returning undefined or empty lists early let me scrap all the error cases at the beginning.  This cleaned up my code.  Then I started using early return cases for edge cases that didn't follow the main flow.  Such as `if isSpecialCase(input)) { return handleSpecialCase(input); }`.  Not sure what other uses I will find later, but I think the problem the teacher is trying to address is very disorganized code by beginners which isn't bad intent by any means.
aaaaaa
CC BY-SA 3.0
2018-03-12T13:22:23.623Z
@DavidZ After priority #1 (working code), isn't just about any design pattern and rule we have ever heard about just a means to fulfill priority #2? Thus not only _can_ rules be bent, but they _should_ be bent to that aim if it clears up code. Of course, whether your own code is clear is not always easy to judge, so we have rules to give people objecive criteria they can hang on to.
Arthur
CC BY-SA 3.0
2018-03-12T17:11:29.663Z
Some languages virtually require it. It's not possible to write idiomatic Go, for instance, without returning early. Or understandable Go, for that matter.
Michael Hampton
CC BY-SA 3.0
2018-03-13T14:36:29.883Z
function foo() { if (!foo_enabled()) { return false; } /* lots and lots of code here */ } 
What could be more readable then this?
Tero Lahtinen
CC BY-SA 4.0
2019-02-20T01:34:53.847Z
Revisiting this almost a year later, it occurs to me that you can only really make this case in languages that support some construct like `finally` that can be executed unconditionally. (Some other features that provide this sort of functionality are Python's context managers, C#'s `IDisposable`, and Java's `try`-with-resources.) Without that, single return will likely serve you well in situations where you need to release a resource. Students should be made aware of that reality, at minimum.
jpmc26
CC BY-SA 4.0
2022-05-20T20:37:57.937Z
You say: "If you return only at the end, say `return result;` then … You have to understand it 'as a whole'. ". I would argue the opposite for exactly the same reason. If you have `returns`/`goto`s nested in `if`s, then you have to understand all levels of the indentation at the same time. However, I agree with "Of course if you always write three statement methods, this won't occur.", but you are still left with these nested returns to trip you up.
ctrl-alt-delor
CC BY-SA 3.0
2018-03-09T18:32:12.223Z
2018-03-09T18:54:03.780Z
2018-03-09T18:54:03.780Z
Buffy
<p>Speaking as a computer science professional (not an educator) with over 40 years of experience, the important thing to teach is <strong>discipline</strong>.  Would-be programmers need to understand that code which is poorly structured and disorganized leads to both confusion and "stupid" coding errors.</p>

<p>The criteria you give is a good first cut at a set of "rules" in this area, but it's important to appreciate <em>why</em> the rules are there.</p>

<p>In real life code is <em>maintained</em>, meaning that you or some co-worker may come back months or years later to make some "minor" change.  If the person making the change does not, eg, notice that a <code>return</code> is embedded inside an <code>else</code> statement inside a loop then the conditions are set up to introduce a bug.  (Similarly, if a bunch of nested <code>if/then</code> statements are coded without associated <code>do/end</code> statements then it's easy to accidentally mess things up.)</p>

<p>It's not the specific rules that is important, it's the <em>purpose</em> behind the rules.  As languages (and coding styles) morph and change the specific rules will come and go, but the <em>purpose</em> remains to make the structure of the program visually evident, and to make "stupid" coding errors during program modification less likely.</p>

CC BY-SA 3.0
2018-03-11T02:43:52.583Z
2018-03-11T02:43:52.583Z
Hot Licks
<blockquote>
<p>Is it a wrong approach, giving your students the choice? Or is it wrong to force them never to return early?</p>
</blockquote>
<p>This is a false dichotomy.  Sometimes multiple returns are clearer, and sometimes (rarely) a single return is clearer.  You should encourage (&quot;force&quot; is a rather strong word) your students to use the technique which makes the most sense for any given scenario.</p>
<p>There is one, very specific, situation where &quot;one entry, one exit&quot; makes sense, but it is not something you should expose to beginners, and it is also most likely not what your colleague is talking about.  It may still make sense to show at more advanced levels, for students who might (for example) submit pull requests to Linux or Git.</p>
<p>The problem, you see, is C.  C does not have any of the following:</p>
<ul>
<li>C++'s destructors and RAII.</li>
<li>Java's try-with-resources.</li>
<li>Python's <code>with</code> statement and context managers.</li>
<li>Go's <code>defer</code>.</li>
<li>C#'s <code>using</code> and <code>IDisposable</code>.</li>
<li>The <code>finally</code> block, from numerous languages with exceptions including most of the above.</li>
</ul>
<p>As a result, the organization of cleanup code in C is quite different from higher-level languages.  Essentially, the typical way to do cleanup in C is like this:</p>
<pre class="lang-c prettyprint-override"><code>int read_some_type(char *filename, struct some_type *result){
    int rc = 0;
    if(!result){
        rc = -1;
        goto out;
    }
    int fd = open(filename, O_RDONLY);
    if(fd == -1){
        rc = -1;
        goto out;
    }
    // Normally we'd allocate this on the stack; assume struct some_type is huge.
    char *str = malloc(sizeof(struct some_type));
    if(!str){
        rc = -1;
        goto out_open;
    }
    ssize_t size;
    size_t total = 0;
    while(total != sizeof(struct some_type)){
        size = read(fd, &amp;str[total], total - sizeof(struct some_type));
        if(size &lt;= 0){
            rc = -1;
            goto out_malloc;
        }
        total += size;
    }
    memcpy(result, str, sizeof(struct some_type));
out_malloc:
    free(str);
out_open:
    close(fd);
out:
    // This is strictly unnecessary, but we could add code here in the future.
    // For example, we might check errno and call perror(3) or similar.
    return rc;
}
</code></pre>
<hr />
<p>Needless to say, this is <em>not</em> &quot;using a flag&quot; as your colleague is suggesting.  Converting the above example into a flag-based design will result in an excess of <code>if</code> statements, which are too numerous here already.  More importantly, it would require the reader to keep track of the flags' states for more than a line or two, which is greatly harmful to readability.</p>
<p>Moving the cleanup into helper functions is more promising but still infeasible, because:</p>
<ul>
<li>You need a helper function for each managed resource, in each main function that needs to manage a resource, plus another helper function for any cleanup code that needs to execute unconditionally.</li>
<li>Helpers do not automatically inherit the state of their callers and a lot of state may need to be passed around.</li>
<li>The information about which helpers imply which other helpers, and which order the helpers need to be called in, is either repeated throughout the function body and prone to transcription errors, or else the helpers call each other in a chain and must pass around <em>even more</em> state.</li>
<li>Reading the cleanup code sequentially at the end of the function is intuitively straightforward.  Helpers require human context-switching to properly understand.</li>
<li>Functions must have names.</li>
<li>Functions invite reuse, which invites tight coupling between the cleanup code of unrelated modules of the system.  If there really <em>is</em> some lower-level logical operation which needs to be performed in multiple places, then that might make sense as a helper function.</li>
<li>The cleanup blocks are often one-liners, such as <code>close(fd)</code>.  You cannot meaningfully extract that into a helper, because your helper would just be the <code>close()</code> function with a different name.</li>
<li>This function is doing one logical operation (read a <code>struct some_type</code> from a file and extract it into an object in memory).  Breaking it apart into several functions means each helper is no longer performing a single logical operation.  This is both philosophically and pedagogically objectionable, and also harder to read.</li>
</ul>
<p>This is one of the few situations in which you truly <em>need</em> to use <code>goto</code> in order to keep code readable and maintainable.  Since your students might not otherwise be exposed to that kind of situation, it's worth working through a real example, which you might find in Git, Linux, or any sufficiently large and &quot;interesting&quot; C library or application.</p>

CC BY-SA 3.0
2018-03-10T02:00:50.557Z
Sorry, not convincing in most cases. Three helpers is no more infeasible than three code blocks. Nor is is more or less likely to call them in the wrong order vs to order the blocks wrongly. You are closer, though, if the helpers require excessive args or return values, but then, I suspect the code is already so obfuscated that abstracting out this structure doesn't help you much. Probably it need a complete rethinking rather than just throwing more code in one function. Your "Do thing..." sections should probably be factored out, for example. I trust you that code like this exists frequently.
Buffy
CC BY-SA 3.0
2018-03-10T02:31:10.673Z
@Buffy: Expanded and revised.  But regardless of your personal opinion, it should be emphasized that Linus won't accept pull requests which use helper functions.  So if you plan to submit code to Linux or Git, you *must* use the `goto` cleanup method even if you hate it.
Kevin
CC BY-SA 3.0
2018-03-10T02:43:51.587Z
The structure of the code is this. It is a nest of shells (3 or 4 depending). Each shell, say the "do C" shell tries something that might fail. If it fails it cleans up after _itself_ and may signal a containing shell. The "do B" shell has the same structure except that it contains the "do C" shell. It tries something and cleans up after _itself_  if needed and passes error codes to outer any shell (including failure of "do C"). If you code it that way it is much simpler. You don't have to think about much but getting each level correct. That is what you are trying to achieve here, I think.
Buffy
CC BY-SA 3.0
2018-03-10T02:49:11.003Z
Moreover it doesn't contradict the "return as early as you can" idea. Each shell can do that, of course, if no cleanup is needed, but an outer shell can't return until a contained shell does. But that is just the same as occurs when one function calls another. I won't try to stand between you and Linus, of course.
Buffy
CC BY-SA 3.0
2018-03-10T03:44:53.727Z
"but an outer shell can't return until a contained shell does" - Don't you see that the `goto` statements functionally *are* returns?
Kevin
CC BY-SA 3.0
2018-03-10T04:04:22.350Z
I also took the liberty of writing a *real* example, which I think makes it very clear that helper functions would be much harder to read.
Kevin
CC BY-SA 3.0
2018-03-10T04:38:42.413Z
Welcome to [cseducators.se]. I like you post, for what it is. Unfortunately it doesn't actually _answer_ the question. It seems more like a discussion about the the need/usability of single/multiple returns in functional code. Can you edit this to use your information to answer the OP's question about teaching/forcing a single `return` in a subroutine. I believe there could be some gold in these hills, it just has to be mined and refined.
Gypsy Spellweaver
CC BY-SA 3.0
2018-03-10T06:42:28.663Z
@GypsySpellweaver: I do believe I *did* discuss that, in both the first and last paragraphs.  Perhaps if I had not been repeatedly pestered about the viability of this technique, that would have made up a larger component of this answer.  Nevertheless, it does appear to answer the question as asked from where I sit.  Do you have any specific and actionable suggestions?
Kevin
CC BY-SA 3.0
2018-03-10T06:47:33.377Z
Is it wrong to force the _students_ (not active professional team programmers) to only use one `return`? Or is it wrong to allow the students to use multiple `return`s in an understood manner, possibly subject to guidelines from the instructor?
Gypsy Spellweaver
CC BY-SA 3.0
2018-03-10T06:49:00.153Z
@GypsySpellweaver: This is a false dichotomy, as my answer explains in great detail.  There are situations where multiple returns are appropriate and situations where single return is appropriate.
Kevin
CC BY-SA 3.0
2018-03-10T06:55:52.407Z
Simple, and much improved because of it. Now the bulk of the answer _explains_, and supports your answer. Keeping aware of what the students will find _in the wild_ is important, giving them a firm foundation to build on is better than _teaching the test_, as is all too often done in some subject and schools recently.
Gypsy Spellweaver
CC BY-SA 3.0
2018-03-10T07:32:39.173Z
Indeed, welcome to [cseducators.se]. Pestered or no, this is really a wonderful answer. I hope we hear more from you.
Ben I.
CC BY-SA 3.0
2018-03-10T21:12:06.330Z
It is wrong to talk to students about a single vs multi return policy without explaining that it depends on the language. This answer makes clear that single returns are an established `c` pattern. One that should not be dictated to any of these other languages that have their own construct for cleaning up resources.
candied_orange
CC BY-SA 3.0
2018-03-12T11:50:35.983Z
"converting the above example into a flag-based design will result in an excess of if statements, which are too numerous here already."  Too numerous for whom?  You have a nesting conditional structure, which can *and should* be represented neatly with "if" statements.  Instead your code has deliberately obfuscated that structure, which makes it harder to maintain.  If there was a performance benefit then perhaps you could justify it, but there isn't.  Thank you though for a great example of an anti-pattern - I will use this myself for people I mentor, to literally show them how not to do it.
Graham
CC BY-SA 3.0
2018-03-14T16:24:16.723Z
I prefer to avoid "helper functions" as described in this answer. Instead I try to take a different approach _where viable_; that is, to have a function or functions that do the work _only_ do the work. They are called from a memory management function that only does the setup and the cleaning up.  I can return early or do anything else in the work function, and when I do, the clean-up is handled as part of the return from the function instead of the function explicitly having to clean up after itself, worker function or not.
Baldrickk
CC BY-SA 3.0
2018-03-15T17:34:22.123Z
Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackexchange.com/rooms/74580/discussion-on-answer-by-kevin-is-it-bad-to-force-my-students-not-to-return-early).
thesecretmaster
CC BY-SA 4.0
2023-02-10T01:33:48.470Z
I'd like to point out that is basically implementing your own `finally` functionality, which is a sound approach in a language that lacks an explicit implementation of one. The reason to avoid `goto` is because of *misuse* of the feature, and in a language that lacks a replacement for a proper use, you really have no better option. I'm glad we have higher level languages that have made `goto` unnecessary with their own features, but C is a different beast from a time before we knew how to do that.
jpmc26
CC BY-SA 4.0
2018-03-10T01:26:03.500Z
2020-10-05T21:51:12.763Z
2020-10-05T21:51:12.763Z
Kevin
<p>When I learnt Eiffel, I realised that a single return at the end of a function is the way to go. Eiffel does not have a return. You just set the value of the Result variable, and it is returned at the end of the function. The Eiffel style of programming makes this natural.</p>

<p>When I learnt Scheme, I realised that return early was the way to go. In scheme we created cases, and each case would return a different result. The scheme style of programming makes this natural.</p>

<p>When I program in other languages, I use one or the other, depending on my needs. However I <strong>Use one or the other</strong> I don't use something in between. Therefore either do a switch-case-return, or return at end. In between is a mess. </p>

<p>For teaching. Remember there is more than one correct way. You will probably want to teach one at a time. And it would be better to choose a language than supports the style that you are teaching. (There are however infinitely more incorrect/bad ways to do it. I am not saying that all ways are good, just that there are more than one).</p>

CC BY-SA 3.0
2018-03-14T16:26:14.903Z
Some languages make one style prevalent over the other.  Some other languages are more flexible and different coding styles can be used.  What you do there can be defined either by the style, or the algorithm itself - you do what is cleanest.
Baldrickk
CC BY-SA 4.0
2022-05-20T20:41:24.497Z
@Baldrickk your comment, says the same as the answer. Except that it encourages the messy in the middle approach. Mix and match will lead to errors.
ctrl-alt-delor
CC BY-SA 3.0
2018-03-10T13:45:34.860Z
2018-03-10T13:45:34.860Z
ctrl-alt-delor
<p>This is a great opportunity to teach about history of programming and how programming itself evolves over time. Keep in mind that "evolve" is neither a synonym nor an antonym to "improve"; it's an independent word with its own meaning.</p>

<p>20 years ago Single Entry Single Exit was a somewhat popular coding style, but that time has passed. Nowadays the popular style is short functions, early returns, and absence of deep nesting. Source: (because I'm lazy) The answers on this question and their respective vote count.</p>

<p>The above certainly applies to C++ and C#. Popular coding styles can and will differ between different languages - sometimes for practical reasons, sometimes for historical reasons. They will also differ among different companies and different teachers.</p>

<hr>

<p>To actually answer your question: Teach them what coding styles are acceptable in your class, and why. <strong>It doesn't matter <em>which</em> style(s) you chose, but you must answer the <em>why</em></strong>. Also teach them that other coding styles exist, many of which they will encounter in other courses and in their professional career.</p>

CC BY-SA 3.0
2018-03-11T19:31:16.790Z
2018-03-11T20:24:46.273Z
2018-03-11T20:24:46.273Z
Peter
<p>This discussion is adjacent to one of the longest running religious wars in Computer Science - is the &quot;goto&quot; command evil.</p>
<p>Return, break, continue and even the much reviled goto all do the same thing. They disrupt the flow of the code. If you have a math background and think in algorithms then nothing could be more crazy making than a mid-function return because it makes it all but impossible to create proofs of the validity of the code.  If you have an engineering background, are familiar with the code a compiler produces and the clock cycles needed to complete a task then there is nothing more beautiful then a simple jump command.</p>
<p>Two of the venerable grey beards of our discipline Niklaus Wirth and Linus Torvalds have drastically different takes on the topic.  There is a famous exchange with Torvalds where he spells out his point of view (and his opinion of Wirth) in unambiguous detail: <a href="https://koblents.com/Ches/Links/Month-Mar-2013/20-Using-Goto-in-Linux-Kernel-Code/" rel="nofollow noreferrer">Using Goto in Linux Kernel Code</a></p>
<p>What it comes down to:</p>
<ul>
<li>If you like pretty code, sometimes at the expense of readability, then you hate jumps of any kind.</li>
<li>If speed and efficiency is your thing, then its jumping all the way.</li>
</ul>

CC BY-SA 4.0
2022-05-19T16:08:10.970Z
Tnx the Linux link. I was taught by a teacher who once (casually!!) said *What the goto does to control structure, the assignment does to data structure*. That statement was quite an earthquake for me personally. From then on when I'm religious (ie "pure") I stick to functional programming. When not I use goto/break/continue & assignment (in C, python, what-have-you) with equal alacrity.
Rushi
CC BY-SA 4.0
2022-05-19T19:20:57.213Z
@Rusi That sounds too limiting. People like Dijkstra and Hoare have shown how you can perfectly well do formal reasoning about programs with assignments. Those are not nearly as bad as goto's. You don't have to go all the way to single assignment.
Victor Eijkhout
CC BY-SA 4.0
2022-05-20T04:41:30.747Z
@VictorEijkhout Hoare admitted that his formal approach had broadly failed https://en.wikipedia.org/wiki/Tony_Hoare#Apologies_and_retractions. Just as denotational semantics uses environments to mathematize assignment, it uses continuations for gotos. The programming/compiling technique called CPS (continuation passing style) comes from this. And Dijkstra's foibles would overflow this chat medium 
Rushi
CC BY-SA 4.0
2022-05-20T04:56:09.500Z
BTW @codingcat, I read Linus diatribe not primarily as one of «speed and efficiency is your thing» but of cleanliness. Linus finds deep unnecessary nesting uglier (more cognitive load) than strictly stylized goto use. Maybe this should be read in conjunction https://www.zdnet.com/google-amp/article/linus-torvalds-prepares-to-move-the-linux-kernel-to-modern-c/ Which to me can be prized open as *innocuous-looking assignments can pose huge risks*
Rushi
CC BY-SA 4.0
2022-05-20T11:52:35.817Z
@Rusi The topic is assignemnts, not null references. The fact that his techniques did not get taken up does not imply that they don't work. I've used them successfully myself.
Victor Eijkhout
CC BY-SA 4.0
2022-05-20T12:19:17.500Z
@VictorEijkhout I was referring to the second quote in the wiki link re apologies & retractions.
Rushi
CC BY-SA 4.0
2022-05-20T12:55:17.300Z
@Rusi when you look at compiled assembler/opcode you quickly see that cleanliness and speed/efficiency are often the same thing. While working on driver/system software I would often write while-true loops, followed by a list of if-break statements.  In addition to being much easier to follow logically, the compiled code was universally more efficient.
codingCat
CC BY-SA 4.0
2022-05-20T14:24:45.873Z
@Rusi my second sentence referred to his 2nd remark.
Victor Eijkhout
CC BY-SA 4.0
2022-05-20T15:40:39.843Z
Right... So??? Do we have some disagreement @codingCat?? What I find striking about the kernel mailing list exchange you posted is the religious fervour of the anti-goto person.  There is almost not a single *reason/argument* there.  Just an absolute reliance on the EWD-papal bull *Dijkstra said "goto is evil". So it of course is*
Rushi
CC BY-SA 4.0
2022-05-12T14:05:15.430Z
2022-05-19T16:34:49.947Z
2022-05-19T16:34:49.947Z
codingCat
<p>After some reflection on user <a href="/a/4442">Kevin's post here</a>, I thought it might be useful to capture some of the comment discussion permanently and also provide to users who don't use C very much (I don't myself lately), a deeper explanation of what is going on.</p>
<p>I agree with Kevin (hereafter the OP = original poster) that this sort of coding isn't what you teach novices first, and is limited, perhaps, to C-like (even assembly-like) languages. Below, I've modified his example just a bit by trying to explicate the various shells that I discussed in a comment. In particular, the only change has been to add a block structure to the code using braces (which can be opened anywhere and create a new lexical level, though I don't need to use if for renaming variables here). It is just to make the structure (I hope) clearer to the reader and the code archaeologist. I've also given &quot;names&quot; to the blocks/levels/shells, though just as comments.</p>
<pre class="lang-c prettyprint-override"><code>int read_some_type(char *filename, struct some_type *result){
    int rc = 0;
    { //&lt;1&gt; &quot;Code is broken on entry&quot; shell
        if(!result){
            rc = -1;
            goto out;
        }
        { //&lt;2&gt; &quot;Try to open a file&quot; shell
            int fd = open(filename, O_RDONLY);
            if(fd == -1){
                rc = -1;
                goto out;
            }
            { //&lt;3&gt; &quot;Try to allocate&quot; shell
                // Normally we'd allocate this on the stack; assume struct some_type is huge.
                char *str = malloc(sizeof(struct some_type));
                if(!str){
                    rc = -1;
                    goto out_open;
                }
                { //&lt;4&gt; &quot;Evaluate and act&quot; shell
                    ssize_t size;
                    size_t total = 0;
                    while(total != sizeof(struct some_type)){
                        size = read(fd, &amp;str[total], total - sizeof(struct some_type));
                        if(size &lt;= 0){
                            rc = -1;
                            goto out_malloc;
                        }
                        total += size;
                    }
                    memcpy(result, str, sizeof(struct some_type));
                    out_malloc:
                } //&lt;/4&gt;
                free(str);
                out_open:
            } //&lt;/3&gt; 
            close(fd);
        out:
        } //&lt;/2&gt;
    } //&lt;/1&gt;
    // This is strictly unnecessary, but we could add code here in the future.
    // For example, we might check errno and call perror(3) or similar.
    return rc;
}
</code></pre>
<p>Each &quot;shell&quot; is now a block. Each shell tries to do something that might fail. Each shell ends with a label. Each &quot;goto&quot; is essentially a return from the shell, as was noted by the OP and I also noticed. Each shell is immediately followed by cleanup from that shell. This is a special case, actually, since here the cleanup needs to be done both on success and failure of the overall code. If the cleanup were only needed on failure, the innermost shell could do an immediate return after success is achieved, though goto out here is equivalent as there is no code following that label.</p>
<p>If you think about the code, while it doesn't use &quot;helper&quot; functions, in effect what it is is a bunch of helper functions expanded in place (inlined) rather than called explicitly. The lexical structure replaces arguments. This sort of thing (inlining) is often used for efficiency (and making Torvalds happy, I guess). But in most coding efficiency is the last thing you need to consider (after writing clearer code and then running a profiler to see where efficiency suffers). Kernel code in an OS is an obvious exception, of course.</p>
<p>It is also important to note that each shell cleans up after itself. So both allocation and the needed deallocation take place within the same shell. Similarly for the file handling.</p>
<p>Moreover, if you are going to code this way you need to be absolutely pure in your implementation of it. It is fine to add a new shell, inner to another as long as you keep the same discipline. You don't need to create the extra blocks as I've done here, but you do need to write as if they exist. If you use additional goto statements to jump between the shells/blocks you will have a mess.</p>
<p>Also, if you treat the goto statements as &quot;returns&quot; from the shell, then the idea of &quot;returning as soon as you can&quot; is still in place. Here, you &quot;return&quot; when you notice a failure (say of <em>malloc</em>). But you also &quot;return&quot; at the end of the shell by falling through to the outer shell.</p>
<hr />
<p>The code is also a bit special since two of the shells (#1 and #2) end at the same place, though that isn't the general situation. In general there might be two different targets for what is, here, the <em>out</em> label. That label would be after the end of the #2 shell at the end of #1</p>
<hr />
<p>Note this post is &quot;owned&quot; by the community so you are free to improve it as well as comment on it. In particular, I'd be interested in hearing from the OP whether making these shells/levels explicit would be considered to be a good or bad thing in his environment.</p>

CC BY-SA 3.0
2018-03-11T17:16:47.677Z
Personally, I find the extra indents much harder to read (consult also the [kernel style guide on indentation](https://www.kernel.org/doc/html/v4.10/process/coding-style.html#indentation), which *de facto* bans this because there are too many levels of indentation).  But I do agree that this might be pedagogically useful, to help students understand what the gotos are for and why we use them.  I just can't imagine seeing it "in the wild."
Kevin
CC BY-SA 4.0
2018-03-11T13:32:19.753Z
2020-10-05T20:42:36.273Z
2020-10-05T20:42:36.273Z
Buffy
<p>A fellow teacher of mine is teaching "basic algorithms" course in high school, and we have quite conflicting opinions when it comes to <code>return</code>ing from functions.</p>

<p>She restricts <code>return</code> only to the end of the function, and permits no other way to escape functions. No block guards, too, and no breaking loops using <code>return</code>.</p>

<p>To be clear, the approach she teaches her student with is "Single Entry, Single Exit", when the exit is at the function's end and does not break a loop (instead she prefers using flags, even though sometimes in my opinion it makes the code messier).</p>

<p>In contrast, I prefer teaching my students the option to return early and how it affects their code and flow, and let them decide by themselves what they think is right to do. The criteria guidelines I usually teach are:</p>

<ul>
<li>Do you return early because of your functions logic, or because you were given an exceptional parameter/erroneous parameter? If we're talking about the latter, <em>it is ok to return.</em></li>
<li>Are you able to avoid returning in the middle without the cost of changing your whole control flow? If not, <em>it is ok to return.</em></li>
<li>Will avoiding returning early add unnecessary nesting levels to the function? If so, <em>it is ok to return.</em></li>
</ul>

<p>Is it a wrong approach, giving your students the choice? Or is it wrong to force them never to return early?</p>

<p><strong>Edit</strong> the answers suggested some very interesting difference between many languages. We are teaching C#, which is a high level language, so I wasn't considering <code>jmp</code>s of assembly or lower level C's deallocation of resources.</p>

CC BY-SA 3.0
2018-03-10T01:28:23.123Z
(Highly?) relevant question from StackOverflow: https://stackoverflow.com/questions/36707/should-a-function-have-only-one-return-statement
tonysdg
CC BY-SA 3.0
2018-03-10T14:41:36.900Z
@tonysdg Maybe (Highly?er) relevant answer from Software Engineering: https://softwareengineering.stackexchange.com/a/118793/275869
Gypsy Spellweaver
CC BY-SA 3.0
2018-03-11T13:11:28.100Z
Comments are for suggesting improvments on the question or requesting more information; feel free to continue this discussion [in chat](https://chat.stackexchange.com/rooms/74339/discussion-on-question-by-yotam-salmon-is-it-bad-to-force-my-students-not-to-ret).
thesecretmaster
CC BY-SA 3.0
2018-03-15T05:42:43.977Z
Early or late returns, or both.  Mid-block returns, and returns from loops and nested if statements are smells, and why they should be avoided can be explained in easy terms of hiding the intent (loops should terminate when items are found, deeply nested conditions should be made early checks or the mainline logic)
Edwin Buck
CC BY-SA 4.0
2022-05-20T20:33:21.573Z
If this a question about teaching. Or about whether structured programming is a good idea. Whether `goto` is considered harmful. Whether you should be able to have an idea of what you code does if folded (folding= collapsing the view of functions / selection / iterations, into a single line).
ctrl-alt-delor
<best-practice><secondary-education>
Is it bad to force my students not to return early?
# Is it bad to force my students not to return early?

(Asked by: username_0 on 2018-03-09)

A fellow teacher of mine is teaching "basic algorithms" course in high school, and we have quite conflicting opinions when it comes to `return`ing from functions.

She restricts `return` only to the end of the function, and permits no other way to escape functions. No block guards, too, and no breaking loops using `return`.

To be clear, the approach she teaches her student with is "Single Entry, Single Exit", when the exit is at the function's end and does not break a loop (instead she prefers using flags, even though sometimes in my opinion it makes the code messier).

In contrast, I prefer teaching my students the option to return early and how it affects their code and flow, and let them decide by themselves what they think is right to do. The criteria guidelines I usually teach are:

* Do you return early because of your functions logic, or because you were given an exceptional parameter/erroneous parameter? If we're talking about the latter, *it is ok to return.*
* Are you able to avoid returning in the middle without the cost of changing your whole control flow? If not, *it is ok to return.*
* Will avoiding returning early add unnecessary nesting levels to the function? If so, *it is ok to return.*

Is it a wrong approach, giving your students the choice? Or is it wrong to force them never to return early?

**Edit** the answers suggested some very interesting difference between many languages. We are teaching C#, which is a high level language, so I wasn't considering `jmp`s of assembly or lower level C's deallocation of resources.

**Tags:** best-practice, secondary-education

> **Comments:**
> **username_1**: (Highly?) relevant question from StackOverflow: https://stackoverflow.com/questions/36707/should-a-function-have-only-one-return-statement  
> **username_2**: @username_1 Maybe (Highly?er) relevant answer from Software Engineering: https://softwareengineering.stackexchange.com/a/118793/275869  
> **username_3**: Comments are for suggesting improvments on the question or requesting more information; feel free to continue this discussion [in chat](https://chat.stackexchange.com/rooms/74339/discussion-on-question-by-yotam-salmon-is-it-bad-to-force-my-students-not-to-ret).  
> **username_4**: Early or late returns, or both.  Mid-block returns, and returns from loops and nested if statements are smells, and why they should be avoided can be explained in easy terms of hiding the intent (loops should terminate when items are found, deeply nested conditions should be made early checks or the mainline logic)  
> **username_5**: If this a question about teaching. Or about whether structured programming is a good idea. Whether `goto` is considered harmful. Whether you should be able to have an idea of what you code does if folded (folding= collapsing the view of functions / selection / iterations, into a single line).  

---

## 11 answers

### Answer by username_15 on 2018-03-09. Score: 149 | Accepted answer

Actually returning early should be the norm. Return as soon as you can. There are at least two reasons for this, of which the first, efficiency, is the least important. But if you return early then needless statements won't be executed. Nor will you need to devise some special code to get to the end just so that you can return.

However, the biggest and most important reason for returning early is that the programmer can put a limit on what she/he needs to retain mentally about the state of the computation. This is especially helpful in a sequential if situation. There is actually an Elementary Pattern about this ("Return, not else") that says that if you know what should be returned at the end of an if block, don't use an else, but instead end the block with the return. The reader/writer/updater then gets to ignore the previous state and start over in their thinking process.

If you return only at the end, say "return result;" then you have to track all changes to *result* that might occur anywhere in the function/method. You have to understand it "as a whole" rather than incrementally. But the reading itself is normally sequential and incremental.

Of course if you always write three statement methods, this won't occur, but few have the discipline to really do that. Sadly, some programmers can't understand their own code when it contains very many nested structures and tests.

I'll also note that this is somewhat related to the idea that we generally try to avoid global variables in programming. Too much extraneous information can impinge on understanding. Being able to comprehend a program "one block at a time" without reference to others, even containing blocks, is a big advantage.

---

Caveat. Of course, the code should be as clear as possible. If returning late makes it clearer, I wouldn't *forbid* it. But I think that is seldom the case. Forbidding early returns, however, is counterproductive.

> **Comments:**
> **username_16**: I think that caveat is more important than calling it a "caveat" may suggest. I'm of the opinion that clear and understandable code is priority #1 (well, maybe #2 after _working_ code), and all other rules can be bent to that aim. But if you do want to have a general principle about early returns, I definitely agree that allowing and even encouraging them seems like a better choice than forbidding them, for exactly the reasons you describe.  
> **username_1**: I'd also like to add a caveat -- this answer makes a lot of sense in a high school context, where the language is probably high-level (Python, Java, etc.) with managed memory. In lower-level languages (e.g., C), returning late may make for [much cleaner and more readable code](https://stackoverflow.com/a/245761/5003848).  
> **username_15**: @username_1, I don't find the code you link to very compelling. I can make it much cleaner and more understandable with no goto statements at all. For example, within the limits of formatting here, a part of it could be: `if (!doB()) {undoB(); undoA(); return;}` (undoing both B and A)  
> **username_1**: @username_15: The second comment on that answer says the very same thing actually :) I guess I personally find the format in that link to be very clean -- it reminds me of unwinding a stack -- but I see your point. I'll also point to [this answer](https://stackoverflow.com/questions/24451/is-it-ever-advantageous-to-use-goto-in-a-language-that-supports-loops-and-func/24476#24476) on a separate question -- the answer and its comments have (IMO) thought-provoking points about the pros and cons of various forms of control flow (`return` and `goto` included). Probably out of scope for high school tho.  
> **username_13**: Modern optimizers are pretty sharp about implementing return early even when you don't do it in your code. The efficiency argument is not as strong as it was when I was learning.  
> **username_17**: I was taught never to return early.  Then in javascript I realized returning undefined or empty lists early let me scrap all the error cases at the beginning.  This cleaned up my code.  Then I started using early return cases for edge cases that didn't follow the main flow.  Such as `if isSpecialCase(input)) { return handleSpecialCase(input); }`.  Not sure what other uses I will find later, but I think the problem the teacher is trying to address is very disorganized code by beginners which isn't bad intent by any means.  
> **username_18**: @DavidZ After priority #1 (working code), isn't just about any design pattern and rule we have ever heard about just a means to fulfill priority #2? Thus not only _can_ rules be bent, but they _should_ be bent to that aim if it clears up code. Of course, whether your own code is clear is not always easy to judge, so we have rules to give people objecive criteria they can hang on to.  
> **username_19**: Some languages virtually require it. It's not possible to write idiomatic Go, for instance, without returning early. Or understandable Go, for that matter.  
> **username_20**: function foo() { if (!foo_enabled()) { return false; } /* lots and lots of code here */ }  What could be more readable then this?  
> **username_12**: Revisiting this almost a year later, it occurs to me that you can only really make this case in languages that support some construct like `finally` that can be executed unconditionally. (Some other features that provide this sort of functionality are Python's context managers, C#'s `IDisposable`, and Java's `try`-with-resources.) Without that, single return will likely serve you well in situations where you need to release a resource. Students should be made aware of that reality, at minimum.  
> **username_5**: You say: "If you return only at the end, say `return result;` then … You have to understand it 'as a whole'. ". I would argue the opposite for exactly the same reason. If you have `returns`/`goto`s nested in `if`s, then you have to understand all levels of the indentation at the same time. However, I agree with "Of course if you always write three statement methods, this won't occur.", but you are still left with these nested returns to trip you up.  

---

### Answer by username_12 on 2018-03-10. Score: 52

Teach your students about the `return` early philosophy. Teach your students about the single `return` philosophy. Tell them this debate is not settled. Explain to them that different software development teams have different opinions and different standards, and that it's important for them to have both these tools in their toolbox for their jobs.

Explain the risks of each:

* Return early can result in mistakes where the function is modified so that something that should happen unconditionally doesn't or only happens under the wrong conditions.
* Single return carries the risk that a change that should happen only conditionally might be accidentally made unconditionally or under the wrong conditions.

Both of these risks are greater if the function is particularly long or complex or if the change is a state modification (e.g., database commit). Explain to them that this is a good reason to prefer shorter functions and stateless code when feasible. The important thing is to make the code easier to understand and easier to modify without making mistakes.

Now let them decide when they write their own code. Then give them an assignment to modify their code that carries these risks and let them try it out.

Also use it as a chance to caution them about being dogmatic in software design. Writing software is full of things where there's no clear cut, *always* right answer. The right choice very often depends on the specific situation and sometimes even the culture of a particular team.

> **Comments:**
> **username_13**: +1 A function that won't fit in one screen of text is usually too long and needs to be broken up (except when it isn't)  
> **username_14**: It's also important to teach them about coding standards, and that those standards will probably dictate which one they must use.  
> **username_12**: @DoctorJones I wouldn't say "probably," as a lot of shops won't have something like this formally documented. ;) And unless you're working on something that's life and death, a standard to this level of detail is probably too heavy weight. But yes, they should be aware that it's possible.  

---

### Answer by username_22 on 2018-03-10. Score: 34

Is it a wrong approach, giving your students the choice? Or is it wrong to force them never to return early?

This is a false dichotomy.  Sometimes multiple returns are clearer, and sometimes (rarely) a single return is clearer.  You should encourage ("force" is a rather strong word) your students to use the technique which makes the most sense for any given scenario.
There is one, very specific, situation where "one entry, one exit" makes sense, but it is not something you should expose to beginners, and it is also most likely not what your colleague is talking about.  It may still make sense to show at more advanced levels, for students who might (for example) submit pull requests to Linux or Git.
The problem, you see, is C.  C does not have any of the following:

C++'s destructors and RAII.
Java's try-with-resources.
Python's with statement and context managers.
Go's defer.
C#'s using and IDisposable.
The finally block, from numerous languages with exceptions including most of the above.

As a result, the organization of cleanup code in C is quite different from higher-level languages.  Essentially, the typical way to do cleanup in C is like this:
int read_some_type(char *filename, struct some_type *result){
    int rc = 0;
    if(!result){
        rc = -1;
        goto out;
    }
    int fd = open(filename, O_RDONLY);
    if(fd == -1){
        rc = -1;
        goto out;
    }
    // Normally we'd allocate this on the stack; assume struct some_type is huge.
    char *str = malloc(sizeof(struct some_type));
    if(!str){
        rc = -1;
        goto out_open;
    }
    ssize_t size;
    size_t total = 0;
    while(total != sizeof(struct some_type)){
        size = read(fd, &str[total], total - sizeof(struct some_type));
        if(size <= 0){
            rc = -1;
            goto out_malloc;
        }
        total += size;
    }
    memcpy(result, str, sizeof(struct some_type));
out_malloc:
    free(str);
out_open:
    close(fd);
out:
    // This is strictly unnecessary, but we could add code here in the future.
    // For example, we might check errno and call perror(3) or similar.
    return rc;
}


Needless to say, this is not "using a flag" as your colleague is suggesting.  Converting the above example into a flag-based design will result in an excess of if statements, which are too numerous here already.  More importantly, it would require the reader to keep track of the flags' states for more than a line or two, which is greatly harmful to readability.
Moving the cleanup into helper functions is more promising but still infeasible, because:

You need a helper function for each managed resource, in each main function that needs to manage a resource, plus another helper function for any cleanup code that needs to execute unconditionally.
Helpers do not automatically inherit the state of their callers and a lot of state may need to be passed around.
The information about which helpers imply which other helpers, and which order the helpers need to be called in, is either repeated throughout the function body and prone to transcription errors, or else the helpers call each other in a chain and must pass around even more state.
Reading the cleanup code sequentially at the end of the function is intuitively straightforward.  Helpers require human context-switching to properly understand.
Functions must have names.
Functions invite reuse, which invites tight coupling between the cleanup code of unrelated modules of the system.  If there really is some lower-level logical operation which needs to be performed in multiple places, then that might make sense as a helper function.
The cleanup blocks are often one-liners, such as close(fd).  You cannot meaningfully extract that into a helper, because your helper would just be the close() function with a different name.
This function is doing one logical operation (read a struct some_type from a file and extract it into an object in memory).  Breaking it apart into several functions means each helper is no longer performing a single logical operation.  This is both philosophically and pedagogically objectionable, and also harder to read.

This is one of the few situations in which you truly need to use goto in order to keep code readable and maintainable.  Since your students might not otherwise be exposed to that kind of situation, it's worth working through a real example, which you might find in Git, Linux, or any sufficiently large and "interesting" C library or application.

> **Comments:**
> **username_15**: Sorry, not convincing in most cases. Three helpers is no more infeasible than three code blocks. Nor is is more or less likely to call them in the wrong order vs to order the blocks wrongly. You are closer, though, if the helpers require excessive args or return values, but then, I suspect the code is already so obfuscated that abstracting out this structure doesn't help you much. Probably it need a complete rethinking rather than just throwing more code in one function. Your "Do thing..." sections should probably be factored out, for example. I trust you that code like this exists frequently.  
> **username_22**: @username_15: Expanded and revised.  But regardless of your personal opinion, it should be emphasized that Linus won't accept pull requests which use helper functions.  So if you plan to submit code to Linux or Git, you *must* use the `goto` cleanup method even if you hate it.  
> **username_15**: The structure of the code is this. It is a nest of shells (3 or 4 depending). Each shell, say the "do C" shell tries something that might fail. If it fails it cleans up after _itself_ and may signal a containing shell. The "do B" shell has the same structure except that it contains the "do C" shell. It tries something and cleans up after _itself_  if needed and passes error codes to outer any shell (including failure of "do C"). If you code it that way it is much simpler. You don't have to think about much but getting each level correct. That is what you are trying to achieve here, I think.  
> **username_15**: Moreover it doesn't contradict the "return as early as you can" idea. Each shell can do that, of course, if no cleanup is needed, but an outer shell can't return until a contained shell does. But that is just the same as occurs when one function calls another. I won't try to stand between you and Linus, of course.  
> **username_22**: "but an outer shell can't return until a contained shell does" - Don't you see that the `goto` statements functionally *are* returns?  
> **username_22**: I also took the liberty of writing a *real* example, which I think makes it very clear that helper functions would be much harder to read.  
> **username_2**: Welcome to [cseducators.se]. I like you post, for what it is. Unfortunately it doesn't actually _answer_ the question. It seems more like a discussion about the the need/usability of single/multiple returns in functional code. Can you edit this to use your information to answer the OP's question about teaching/forcing a single `return` in a subroutine. I believe there could be some gold in these hills, it just has to be mined and refined.  
> **username_22**: @GypsySpellweaver: I do believe I *did* discuss that, in both the first and last paragraphs.  Perhaps if I had not been repeatedly pestered about the viability of this technique, that would have made up a larger component of this answer.  Nevertheless, it does appear to answer the question as asked from where I sit.  Do you have any specific and actionable suggestions?  
> **username_2**: Is it wrong to force the _students_ (not active professional team programmers) to only use one `return`? Or is it wrong to allow the students to use multiple `return`s in an understood manner, possibly subject to guidelines from the instructor?  
> **username_22**: @GypsySpellweaver: This is a false dichotomy, as my answer explains in great detail.  There are situations where multiple returns are appropriate and situations where single return is appropriate.  
> **username_2**: Simple, and much improved because of it. Now the bulk of the answer _explains_, and supports your answer. Keeping aware of what the students will find _in the wild_ is important, giving them a firm foundation to build on is better than _teaching the test_, as is all too often done in some subject and schools recently.  
> **username_8**: Indeed, welcome to [cseducators.se]. Pestered or no, this is really a wonderful answer. I hope we hear more from you.  
> **username_23**: It is wrong to talk to students about a single vs multi return policy without explaining that it depends on the language. This answer makes clear that single returns are an established `c` pattern. One that should not be dictated to any of these other languages that have their own construct for cleaning up resources.  
> **username_24**: "converting the above example into a flag-based design will result in an excess of if statements, which are too numerous here already."  Too numerous for whom?  You have a nesting conditional structure, which can *and should* be represented neatly with "if" statements.  Instead your code has deliberately obfuscated that structure, which makes it harder to maintain.  If there was a performance benefit then perhaps you could justify it, but there isn't.  Thank you though for a great example of an anti-pattern - I will use this myself for people I mentor, to literally show them how not to do it.  
> **username_25**: I prefer to avoid "helper functions" as described in this answer. Instead I try to take a different approach _where viable_; that is, to have a function or functions that do the work _only_ do the work. They are called from a memory management function that only does the setup and the cleaning up.  I can return early or do anything else in the work function, and when I do, the clean-up is handled as part of the return from the function instead of the function explicitly having to clean up after itself, worker function or not.  
> **username_3**: Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackexchange.com/rooms/74580/discussion-on-answer-by-kevin-is-it-bad-to-force-my-students-not-to-return-early).  
> **username_12**: I'd like to point out that is basically implementing your own `finally` functionality, which is a sound approach in a language that lacks an explicit implementation of one. The reason to avoid `goto` is because of *misuse* of the feature, and in a language that lacks a replacement for a proper use, you really have no better option. I'm glad we have higher level languages that have made `goto` unnecessary with their own features, but C is a different beast from a time before we knew how to do that.  

---

### Answer by username_5 on 2018-03-10. Score: 13

When I learnt Eiffel, I realised that a single return at the end of a function is the way to go. Eiffel does not have a return. You just set the value of the Result variable, and it is returned at the end of the function. The Eiffel style of programming makes this natural.

When I learnt Scheme, I realised that return early was the way to go. In scheme we created cases, and each case would return a different result. The scheme style of programming makes this natural.

When I program in other languages, I use one or the other, depending on my needs. However I **Use one or the other** I don't use something in between. Therefore either do a switch-case-return, or return at end. In between is a mess.

For teaching. Remember there is more than one correct way. You will probably want to teach one at a time. And it would be better to choose a language than supports the style that you are teaching. (There are however infinitely more incorrect/bad ways to do it. I am not saying that all ways are good, just that there are more than one).

> **Comments:**
> **username_25**: Some languages make one style prevalent over the other.  Some other languages are more flexible and different coding styles can be used.  What you do there can be defined either by the style, or the algorithm itself - you do what is cleanest.  
> **username_5**: @username_25 your comment, says the same as the answer. Except that it encourages the messy in the middle approach. Mix and match will lead to errors.  

---

### Answer by username_21 on 2018-03-11. Score: 12

Speaking as a computer science professional (not an educator) with over 40 years of experience, the important thing to teach is **discipline**. Would-be programmers need to understand that code which is poorly structured and disorganized leads to both confusion and "stupid" coding errors.

The criteria you give is a good first cut at a set of "rules" in this area, but it's important to appreciate *why* the rules are there.

In real life code is *maintained*, meaning that you or some co-worker may come back months or years later to make some "minor" change. If the person making the change does not, eg, notice that a `return` is embedded inside an `else` statement inside a loop then the conditions are set up to introduce a bug. (Similarly, if a bunch of nested `if/then` statements are coded without associated `do/end` statements then it's easy to accidentally mess things up.)

It's not the specific rules that is important, it's the *purpose* behind the rules. As languages (and coding styles) morph and change the specific rules will come and go, but the *purpose* remains to make the structure of the program visually evident, and to make "stupid" coding errors during program modification less likely.


---

### Answer by username_26 on 2018-03-11. Score: 3

This is a great opportunity to teach about history of programming and how programming itself evolves over time. Keep in mind that "evolve" is neither a synonym nor an antonym to "improve"; it's an independent word with its own meaning.

20 years ago Single Entry Single Exit was a somewhat popular coding style, but that time has passed. Nowadays the popular style is short functions, early returns, and absence of deep nesting. Source: (because I'm lazy) The answers on this question and their respective vote count.

The above certainly applies to C++ and C#. Popular coding styles can and will differ between different languages - sometimes for practical reasons, sometimes for historical reasons. They will also differ among different companies and different teachers.

---

To actually answer your question: Teach them what coding styles are acceptable in your class, and why. **It doesn't matter *which* style(s) you chose, but you must answer the *why***. Also teach them that other coding styles exist, many of which they will encounter in other courses and in their professional career.


---

### Answer by username_27 on 2022-05-12. Score: 3

This discussion is adjacent to one of the longest running religious wars in Computer Science - is the "goto" command evil.

Return, break, continue and even the much reviled goto all do the same thing. They disrupt the flow of the code. If you have a math background and think in algorithms then nothing could be more crazy making than a mid-function return because it makes it all but impossible to create proofs of the validity of the code. If you have an engineering background, are familiar with the code a compiler produces and the clock cycles needed to complete a task then there is nothing more beautiful then a simple jump command.

Two of the venerable grey beards of our discipline Niklaus Wirth and Linus Torvalds have drastically different takes on the topic. There is a famous exchange with Torvalds where he spells out his point of view (and his opinion of Wirth) in unambiguous detail: [Using Goto in Linux Kernel Code](https://koblents.com/Ches/Links/Month-Mar-2013/20-Using-Goto-in-Linux-Kernel-Code/)

What it comes down to:

* If you like pretty code, sometimes at the expense of readability, then you hate jumps of any kind.
* If speed and efficiency is your thing, then its jumping all the way.

> **Comments:**
> **username_9**: Tnx the Linux link. I was taught by a teacher who once (casually!!) said *What the goto does to control structure, the assignment does to data structure*. That statement was quite an earthquake for me personally. From then on when I'm religious (ie "pure") I stick to functional programming. When not I use goto/break/continue & assignment (in C, python, what-have-you) with equal alacrity.  
> **username_10**: @Rusi That sounds too limiting. People like Dijkstra and Hoare have shown how you can perfectly well do formal reasoning about programs with assignments. Those are not nearly as bad as goto's. You don't have to go all the way to single assignment.  
> **username_9**: @VictorEijkhout Hoare admitted that his formal approach had broadly failed https://en.wikipedia.org/wiki/Tony_Hoare#Apologies_and_retractions. Just as denotational semantics uses environments to mathematize assignment, it uses continuations for gotos. The programming/compiling technique called CPS (continuation passing style) comes from this. And Dijkstra's foibles would overflow this chat medium   
> **username_9**: BTW @codingcat, I read Linus diatribe not primarily as one of «speed and efficiency is your thing» but of cleanliness. Linus finds deep unnecessary nesting uglier (more cognitive load) than strictly stylized goto use. Maybe this should be read in conjunction https://www.zdnet.com/google-amp/article/linus-torvalds-prepares-to-move-the-linux-kernel-to-modern-c/ Which to me can be prized open as *innocuous-looking assignments can pose huge risks*  
> **username_10**: @Rusi The topic is assignemnts, not null references. The fact that his techniques did not get taken up does not imply that they don't work. I've used them successfully myself.  
> **username_9**: @VictorEijkhout I was referring to the second quote in the wiki link re apologies & retractions.  
> **username_27**: @Rusi when you look at compiled assembler/opcode you quickly see that cleanliness and speed/efficiency are often the same thing. While working on driver/system software I would often write while-true loops, followed by a list of if-break statements.  In addition to being much easier to follow logically, the compiled code was universally more efficient.  
> **username_10**: @Rusi my second sentence referred to his 2nd remark.  
> **username_9**: Right... So??? Do we have some disagreement @username_27?? What I find striking about the kernel mailing list exchange you posted is the religious fervour of the anti-goto person.  There is almost not a single *reason/argument* there.  Just an absolute reliance on the EWD-papal bull *Dijkstra said "goto is evil". So it of course is*  

---

### Answer by username_15 on 2018-03-11. Score: 3

After some reflection on user username_22's post here, I thought it might be useful to capture some of the comment discussion permanently and also provide to users who don't use C very much (I don't myself lately), a deeper explanation of what is going on.
I agree with username_22 (hereafter the OP = original poster) that this sort of coding isn't what you teach novices first, and is limited, perhaps, to C-like (even assembly-like) languages. Below, I've modified his example just a bit by trying to explicate the various shells that I discussed in a comment. In particular, the only change has been to add a block structure to the code using braces (which can be opened anywhere and create a new lexical level, though I don't need to use if for renaming variables here). It is just to make the structure (I hope) clearer to the reader and the code archaeologist. I've also given "names" to the blocks/levels/shells, though just as comments.
int read_some_type(char *filename, struct some_type *result){
    int rc = 0;
    { //<1> "Code is broken on entry" shell
        if(!result){
            rc = -1;
            goto out;
        }
        { //<2> "Try to open a file" shell
            int fd = open(filename, O_RDONLY);
            if(fd == -1){
                rc = -1;
                goto out;
            }
            { //<3> "Try to allocate" shell
                // Normally we'd allocate this on the stack; assume struct some_type is huge.
                char *str = malloc(sizeof(struct some_type));
                if(!str){
                    rc = -1;
                    goto out_open;
                }
                { //<4> "Evaluate and act" shell
                    ssize_t size;
                    size_t total = 0;
                    while(total != sizeof(struct some_type)){
                        size = read(fd, &str[total], total - sizeof(struct some_type));
                        if(size <= 0){
                            rc = -1;
                            goto out_malloc;
                        }
                        total += size;
                    }
                    memcpy(result, str, sizeof(struct some_type));
                    out_malloc:
                } //
                free(str);
                out_open:
            } // 
            close(fd);
        out:
        } //
    } //
    // This is strictly unnecessary, but we could add code here in the future.
    // For example, we might check errno and call perror(3) or similar.
    return rc;
}

Each "shell" is now a block. Each shell tries to do something that might fail. Each shell ends with a label. Each "goto" is essentially a return from the shell, as was noted by the OP and I also noticed. Each shell is immediately followed by cleanup from that shell. This is a special case, actually, since here the cleanup needs to be done both on success and failure of the overall code. If the cleanup were only needed on failure, the innermost shell could do an immediate return after success is achieved, though goto out here is equivalent as there is no code following that label.
If you think about the code, while it doesn't use "helper" functions, in effect what it is is a bunch of helper functions expanded in place (inlined) rather than called explicitly. The lexical structure replaces arguments. This sort of thing (inlining) is often used for efficiency (and making Torvalds happy, I guess). But in most coding efficiency is the last thing you need to consider (after writing clearer code and then running a profiler to see where efficiency suffers). Kernel code in an OS is an obvious exception, of course.
It is also important to note that each shell cleans up after itself. So both allocation and the needed deallocation take place within the same shell. Similarly for the file handling.
Moreover, if you are going to code this way you need to be absolutely pure in your implementation of it. It is fine to add a new shell, inner to another as long as you keep the same discipline. You don't need to create the extra blocks as I've done here, but you do need to write as if they exist. If you use additional goto statements to jump between the shells/blocks you will have a mess.
Also, if you treat the goto statements as "returns" from the shell, then the idea of "returning as soon as you can" is still in place. Here, you "return" when you notice a failure (say of malloc). But you also "return" at the end of the shell by falling through to the outer shell.

The code is also a bit special since two of the shells (#1 and #2) end at the same place, though that isn't the general situation. In general there might be two different targets for what is, here, the out label. That label would be after the end of the #2 shell at the end of #1

Note this post is "owned" by the community so you are free to improve it as well as comment on it. In particular, I'd be interested in hearing from the OP whether making these shells/levels explicit would be considered to be a good or bad thing in his environment.

> **Comments:**
> **username_22**: Personally, I find the extra indents much harder to read (consult also the [kernel style guide on indentation](https://www.kernel.org/doc/html/v4.10/process/coding-style.html#indentation), which *de facto* bans this because there are too many levels of indentation).  But I do agree that this might be pedagogically useful, to help students understand what the gotos are for and why we use them.  I just can't imagine seeing it "in the wild."  

---

### Answer by username_6 on 2022-05-01. Score: 2

The compiler enforces the rules, everything else is a guideline. It is a bit like ending a sentence with a preposition, about which Winston Churchill said:

> “This is the sort of [English] up with which I will not put.”

In order to satisfy that *guideline* of English usage, sometimes we would end up with an extremely awkward sentence construction. So being a good writer/orator means knowing when to be flexible about the guidelines. Programming is no different. Avoid early returns (if that is the local culture) unless the code ends up being too cryptic in an effort to avoid them. We should encourage the student to develop their judgement about code quality, rather than blindly enforcing guidelines.


---

### Answer by username_7 on 2022-05-19. Score: 1

Forcing the students not to return early is bad, and forcing them to do so is bad as well. See, the issue of whether or not one should use early returns is not only superficial, but also primarily opinion-based, as both approaches are valid considering the individual circumstances. A teacher should not enter the overly authoritative role and impose their subjective stylistic preferences on students. From my own perspective, which is the one of a student, I had encountered a lot of teachers who have been presenting subjective opinions as objective standards, and personal whims as supposedly written gospel. All it succeeded in achieving was confusing all the students from the beginning, and setting all of them for numerous surprising awakenings once a teacher's God-given truth turned out to be a matter of taste, and thus nonsense.

> **Comments:**
> **username_8**: I often present these sorts of preferences as "Most of you don't yet have a philosophy about how to approach __.  I am going to share *my* philosophy with you in this course, and I will also share with you why I think it is so valuable. I ask you to abide by it here. Perhaps after you've lived with it, you'll find value in my approach and wish to take it with you. However, if you later decide that this approach isn't for you, that's fine, too. Believe me, I won't be offended. At that point, at least you'll definitely understand *what* you're rejecting, and that is also a benefit."  
> **username_9**: I've upvoted for the sentiment. But do realize what a deep problem you're unearthing. Newell&Simon described CS as a *Science of the Artificial*. Which implies **There are no objective truths here.**  So then what/how do we teachers teach?  
> **username_8**: @Rusi I'm not sure what you mean.  There's plenty of objective stuff on the mathier side of the field. Information theory certainly seems pretty objective.  There are strict limits on how compressed any information can be encoded.  The halting problem also seems pretty objective.  
> **username_9**: @BenI. The short (& not v useful) answer is things like https://arxiv.org/pdf/math/0209332. And  http://aleteya.cs.buap.mx/~jlavalle/papers/wegner/strong-cct.pdf. But I hasten to add: I'm as uneasy quoting these (without loud grunts!) as I would be saying *Drinking detergent cures covid*. The more relevant arguments are considerably longer. And we can reserve it for chat (if you wish). For here just this much: Your position *State your philosophy underneath your facts* has serious downsides. Students don't typically want high truth but high grades  — not cseducator notwithstanding   
> **username_10**: I sympathize with your point of view, but ask yourself what the other options are. Either your teacher imposes no style at all, or exposes you to *all* styles. Given that as a learner you are unlikely to develop a good style from scratch, I would say that learning at least one consistent style from a teacher is preferable.  

---

### Answer by username_11 on 2018-03-11. Score: 1

I propose that the correct answer is to keep doing what you're doing, by teaching the techniques that you're currently teaching. Both of you.

I was taught with the approach you use. When I was first exposed to the other approach, I didn't much like it. But with an open mind, I learned that the approach used by the other instructor is useful for some analysis processes. Most especially this refers to some particularly older "source code analysis" software tools, but there may be some ongoing benefit to that other style too. As I didn't have experience with the practice of using those specific auditing processes, I'm not in the best position to judge whether the benefits outweigh the pains of constraints.

So, have students be taught both methods.

Maybe students won't like being coerced into being graded on how well they use one method, only to be later graded in another class based on how well they accomplish coding using the other style. The transition may be unpleasant. Tough. That's great.

It is good for students to be prepared for the workforce, and many may benefit greatly from learning that an expected style might not match whatever their personal preference is. If they are allowed to get locked into one style, that may cause challenges in the future when they transition into their first employer, or transition between companies, or even transitioning between different departments of an organization that may have different policies for different departments. Getting the students uncomfortable if they don't adapt may be better for them to experience now.

If having different requirements leads to them being uncomfortable, tell them that different employers may expect different things, and even different projects (e.g., different open source projects) that they may want to become a part of during their off-time. So may different instructors. They are welcome to use whatever approach they want for their own personal hobby projects that they are in charge of, but when other people are in charge, then cooperation can be oodles more important than advantages of a particular style.

So, no, my advice here is: don't give them a choice. Make 'em adapt.

> **Comments:**
> **username_11**: I am reminded of [One's Final Words from ST:Voy (YouTube Video)](https://www.youtube.com/watch?v=yGOYjj2JCN0&t=53s)  Though hopefully not at all for the same reason, if the student gives the same response as what we see from Seven of Nine Tertiary Adjunct of Unimatrix Zero One over the next ten seconds, that effect just might be precisely the best that you can hope for...  

---

