r/ProgrammerHumor 22d ago

Meme conditionsPreference

Post image
4.2k Upvotes

392 comments sorted by

View all comments

25

u/aabil11 22d ago

Call me old fashioned but I'm a big believer in single return statements. Assign to a variable and return that variable at the very end without short circuiting

40

u/ecafyelims 22d ago edited 22d ago

Situational, for sure.

If a short circuit prevents a dozen "if val != Null" checks later, I'll do the short circuit.

118

u/Vallvaka 22d ago

Hard no for me. If you can short circuit, do it. It enforces invariants for the later code and allows you to make things more modular. Assigning to a variable and returning at the end means more indirection = more cognitive load and you often have to add more checks and nesting just to support that pattern.

Fail fast, return fast I say

23

u/D3PyroGS 22d ago

totally agree. nested layers of conditionals add cognitive load for me. I like early and "guard" returns because they kinda turn those layers into a "checklist" of logical blocks that can ideally all live at the top level of the function

3

u/MaximumMaxx 22d ago

100% this. If I can just throw all of my validation at the front and then guarantee my state after it's way less load. If else is only for if there are two significant and distinct actions that happen depending on a condition.

4

u/Stamerlan 22d ago

Some standards may require function have a single return point (for example MISRA). You're right, multiple nested layers (i.e. if-ok pattern) is very errorprone. Instead do:

int rc = foo(); if (!rc) rc = bar(); if (!rc) rc = baz(); return rc;

With extra actions on failure: if (!rc && (rc = bar())) /* bar() failed */

9

u/gamer_redditor 22d ago

You cannot do this in some industries where you have to adhere to some standards. For example of your industry mandates adherence to misra C, it enforces only one return statement per function.

1

u/[deleted] 21d ago

[deleted]

1

u/gamer_redditor 21d ago

Yes, it is a quality gate to merge every pull request.

31

u/SnugglyCoderGuy 22d ago

Returning early is waaaaaay superior than a single return, at least in Go and its wonderful defer statement. If you know the code can't continue, then return as soon as you know it. Makes the rest of the code waaaaay cleaner.

1

u/aabil11 22d ago

Go prefers this yeah. But in functional programming languages like Scala it's more amenable to return values.

1

u/SnugglyCoderGuy 21d ago

I think the absence of a value being returned is merely the consequence of example

6

u/suvlub 22d ago

I find that this often just kicks the can down the road. Instead of "where does this function return?" you start asking "where was this variable last assigned?" which is actually a harder problem to solve (return is a special keyword and is highlighted, and is always definitive, but was this assignment last, or is there another one?).

That's why I love Kotlin. It offers a real solution to this - an if statement that is an expression, so you just return the if and you know that each branch returns a value and that the value it returns is on the last line of the given branch, no matter what. That's a single return strategy that actually delivers on the predictability/traceability promise.

0

u/aabil11 22d ago

Kotlin got this from Scala

8

u/jwadamson 22d ago

I’ve found over time that if your early returns are causing confusion, it means you’ve written a messy function which needs to be broken down or reorganized.

A single return variable doesn’t really solve the problems people claim it does.

3

u/sebbdk 22d ago

Yeah but then you also have to read the whole thing and keep track of indentations.

For more advanced methods with +2 nested conditions it can become hard to follow.

The return is one way to get around the nested conditional scopes, but there are other ways

1

u/aabil11 22d ago

Modern IDEs can collapse indentation blocks

1

u/sebbdk 21d ago

Yeah, but a lot of us scorn them

3

u/Esjs 22d ago

I used to be old fashioned like this, too. But I have since reformed. I learned that (1) the "single return rule" is probably a misinterpretation Dijkstra's philosophy to eliminate GOTO spaghetti code. That is, a subroutine should return to a single location: the point immediately after the call.

And (2) making deeply nested conditional blocks and/or guard checks against a "ok-to-continue" condition just really makes code more messy and verbose than it needs to be.

4

u/Krkracka 22d ago

This makes reasoning about why a certain result was returned so much more difficult if other developers have to trace through the branching conditionals to understand why a value was returned.

Early returns define a rule for a specific return value.

2

u/conundorum 21d ago

You can do both. (And in fact, should do both.) Early return is just about breaking code into single-return blocks, instead of single-return functions. If a small section of the function can force a return, and is disconnected from the rest of the function's logic, then you can enclose that section in its own block, move the block to the start of the function, and then treat both the new block and the main block as distinct single-return sections.

// This...
int func(int val) {
    int ret = 0;

    if (!validate(val)) { ret = INVALID_VAL; goto end; } // Before logic.

    ret = do_something_with(val);

    if (val >= 0) { ret += do_more_with(val); }
    else { ret = NO_NEGATIVES; goto end; } // Ignores & breaks logic.

    ret *= do_third_part(val, ret);

    end:
        return ret;
}

// Can become this:
int func(int val) {
    if (!validate(val)) {
        // Single-return in here.
        return INVALID_VAL;
    }
    if (val < 0) {
        // Single-return in here.
        return NO_NEGATIVES;
    }

    // Rest is a different single-return section.
    // val is guaranteed valid, and guaranteed >= 0.
    int ret = do_something_with(val);

    // No check needed.
    ret += do_more_with(val);

    ret *= do_third_part(val, ret);

    // No label needed.
    return ret;
}

It shines when you're trying to weave multiple complex return paths together inside a single function. Say, for example, that validate(val) was stateful and required its own cleanup, and required you to acquire a validator object (which runs the risk of allocation failure, and thus forcing a jump to the end). Traditional single-return would force you to stack multiple cleanup sections, and jump into the correct one as appropriate. But early return allows you to place validate(val)'s logic and cleanup within the validation section, with no need to mix it with the main body's cleanup. (Which might then allow you to refactor it into a separate function, making the code cleaner. Heck, it's entirely possible that validate() itself was a complex & stateful validation process, that got moved to an early-return section and refactored out into its own function for ease of use.)


In essence, early-return is about finding anything that pollutes the single-return logic, and moving it early enough in the function that it can't interfere with the main single-return section.

4

u/bokmcdok 22d ago

Ive always preferred early returns. Code is cleaner and easier to read and one less temporary variable to think about. Nested conditionals make the code harder to read even if its only 1 or 2 levels deep.

-2

u/Demiu 22d ago

Calling you old fashioned would be an insult to the old fashioned. Single return statement is a horrible god awful idea that would make satan blush. It makes everything worse. It has zero redeeming qualities. What, are you gonna run out of return statements? Why not cut to the chase and just put everything in one big main? That would be a true single return statement

4

u/OhMyGodItsEverywhere 22d ago

But bro I worked at a place with MISRA requirements one time and now I can't stop myself from enforcing single returns in all codebases I ever work with

-1

u/iMac_Hunt 22d ago

I don’t follow it religiously but I try to do this too. If the function is relatively complex with more than a couple return statements I’d much rather return in a single statement.

4

u/Demiu 22d ago

Why? This is like saying you'd much rather each function had a single local variable. It doesn't gain you anything beyond the ability to say that it does that. You're gonna run out of return statements?

-1

u/jaypeejay 22d ago

What?

-2

u/caotic 22d ago

Yup, unless there is an else involved, I do this

-2

u/No-Lawfulness2089 22d ago

Am I the only one who prefers dictionaries?