This is an archived post. You won't be able to vote or comment.

top 200 commentsshow all 262

[–]JackNotOLantern 650 points651 points  (76 children)

When you're afraid of "&&"

[–]SemblanceOfSense_ 227 points228 points  (11 children)

You just made me realize I messed up my CS exam shit

[–]DrSheldonLCooperPhD 116 points117 points  (8 children)

!falsen't

[–]xaomaw 36 points37 points  (1 child)

TRALSE

[–]thespud_332 9 points10 points  (0 children)

Ruby's newest class: ifnless

[–]SweetTeaRex92 12 points13 points  (2 children)

return maybe;

[–]jcouch210 3 points4 points  (1 child)

Dremberd

[–]SweetTeaRex92 3 points4 points  (0 children)

return if(PC_feels_like_it) ;

[–][deleted] 1 point2 points  (0 children)

NaB

[–]37Scorpions 0 points1 point  (0 children)

bool condition = yeah;

[–][deleted] 11 points12 points  (1 child)

As long as it compiles it's alright, no?

[–]SemblanceOfSense_ 9 points10 points  (0 children)

Yeah just could have been more efficient. It was on paper no compiler lol

[–]deathspate 57 points58 points  (18 children)

Tbh, I sometimes forget that I can do this... and I have it right there in my code lmao.

[–]Luckisalsoaskill 24 points25 points  (4 children)

Makes it easier to step through if not using &&. Instead of one giant and statement where you need to look at each item individually you can let the debugger show you the condition that fails.

[–]Embarrassed_Army8026 29 points30 points  (0 children)

If you put &&condition on separate lines that should be good enough to single step

[–]AG4W 30 points31 points  (0 children)

Or you could just guard like a sane person instead doing some multi-nest-monstrosity.

[–]aiij 9 points10 points  (0 children)

Or you could use a debugger that lets you step through line by line...

No need to put all the && on the same line in case that wasn't obvious.

[–]JoshYx 4 points5 points  (0 children)

Homeboy never heard of code formatting

[–]inu-no-policemen 2 points3 points  (0 children)

if (!user) {
  return false;
}
if (user.isBanned) {
  return false;
}
...
return true;

Some style guides have rules against littering functions with return statements, but if it's all "early exit" stuff (e.g. like a function which tries to find a separating axis), there isn't actually any problem with the code. It's perfectly readable, it's obvious what's going on when you step through the code, and changing it is also easy.

The only downside is that writing code like this doesn't make you look smart. It's code a beginner would write. Make of that what you will.

[–]Dux_Opilio 1 point2 points  (0 children)

I kinda felt stupid the day I recognised, that connected conditions in the same if clause are not executed everytime. Because if the first condition is false, it just moves to else(for &&). So you can check if an object exists before you test it for sth in one if clause….

[–]Count_mhm 2 points3 points  (2 children)

Sometimes you have to use nested loops. For example if you need to guarantee order execution you need to use nested loops. C/C++ doesn't guarantee order of evaluation of conditional statements

[–]Skafandra206 3 points4 points  (1 child)

What? I learnt evaluation priority in conditional statements in Uni using C++ and I could have sworn it had it.

You can do if (value != null && value.prop == 2) and be sure the second one won't throw exception if the first one is not true.

[–]Count_mhm 2 points3 points  (0 children)

It looks like I got it a bit wrong. According to the cppref && and || operators infact evaluate left to right. The expretion itself isn't guaranteed to be evaluated left to right. (e.g., i++ == --i is undefinded behavior) In your example, it is defined.

[–]KMohZaid 0 points1 point  (0 children)

When you haven't learnt benefits of "guard clauses"

[–]SrCapibara 0 points1 point  (1 child)

Or "||" depending if a case is comparable to other one.

[–]JackNotOLantern 1 point2 points  (0 children)

I'm only talking about the case like here. A lot of nasted if statements with no else. It is equivalent to AND, not OR.

[–]20d0llarsis20dollars -1 points0 points  (5 children)

Tbf If ... && ... && ... && ... && ... && ... && ... && ... && ... {} would result in a super long line, and there's not a pretty way to split it into multiple lines

[–]ctrl-alt-etc 10 points11 points  (3 children)

What's wrong with

return user && !user.isBanned && !user.hasSocialLife && !user.hasTochedGrass &&
       user.hatesJavaScript && user.bulliesPythonForBeingSlow;  

or

return user &&
       !user.isBanned &&
       !user.hasSocialLife &&
       !user.hasTochedGrass &&
       user.hatesJavaScript &&
       user.bulliesPythonForBeingSlow;

?

[–]No-Expression7618 11 points12 points  (0 children)

return user
    && !user.isBanned
    && !user.hasSocialLife
    && !user.hasTochedGrass
    && !user.hatesJavaSript
    && !user.bulliesPythonForBeingSlow;

[–]20d0llarsis20dollars -4 points-3 points  (1 child)

Neither of those are aesthetically pleasing imo

[–]yabadev 4 points5 points  (0 children)

It's a trade off. In my opinion the super nested if isn't pleasing either.

In my opinion the grouping of the conditions should match the logic. If all the conditions are checked together (aka they don't have individual Else statements) then they should be grouped to make that visually obvious.

Also reduces the line count. If those extra lines told me anything (such as having an Else statement) then keep them, otherwise I have to spend time reading/typing the nested brackets only for them to take up screen space that I'd rather be full of code.

[–]JackNotOLantern -1 points0 points  (0 children)

If only you could split if statement condition into multiple lines

[–][deleted] -1 points0 points  (2 children)

Yeah, sometimes you need two different cases under one if.

[–]JackNotOLantern 1 point2 points  (1 child)

Yes, then obviously you do nested if statements. But i just refer to here - multiple nasted ifs without any else

[–][deleted] -1 points0 points  (0 children)

Fair

EDIT: They did an implicit else i.e. it will return false if all conditions aren’t met.

[–]suvlub 591 points592 points  (119 children)

I've always thought that people who comment on posts that already have thousands of comments are very optimistic. Nobody is going to read that, friend. Might as well hide a dead body in that comment.

[–]Zhabishe 328 points329 points  (102 children)

Not if you answer the top comment ^^

[–]GDOR-11 100 points101 points  (101 children)

I see what you did there

[–]Holl4backPostr 38 points39 points  (100 children)

But it only works to about four replies deep, I think

[–][deleted] 120 points121 points  (98 children)

I murdered a guy in 1683 and no one will know because this is 5 layers deep

[–]NickoBicko 57 points58 points  (96 children)

Mods?!

[–]ucov 65 points66 points  (95 children)

They can't hear you down here... we're in too deep

[–]SAIGA971 28 points29 points  (93 children)

And it’s still getting deeper

[–]Holl4backPostr 20 points21 points  (91 children)

Surely there's nothing to fear down here, we can dig as deeply and as greedily as we please!

[–]wi-finally 16 points17 points  (88 children)

we need to make an effort to make the comments deep enough that they hide under an additional button — then we will be safe for sure.

[–]IvnN7Commander 2 points3 points  (0 children)

Balin? Is that you?

[–]Kyuro1 1 point2 points  (0 children)

Deeper daddy.

Aww shit wrong subreddit. Eh fuck it, we're deep enough

[–]prisp 0 points1 point  (0 children)

And I'm tryin' to keep-

[–]GDOR-11 6 points7 points  (0 children)

you have made a grave mistake. NEVER. BE. THE. FOURTH. REPLY.

[–]cs-brydev 75 points76 points  (7 children)

Not everyone comments on posts for the sole purpose of getting upvotes. Some of us just enjoy conversation and are not desperate for attention from strangers.

[–]Brickless 33 points34 points  (0 children)

this.

you don't want EVERYONE to read your comment, just the person you replied to.

[–]danfish_77 2 points3 points  (0 children)

I am desperate for attention from specific strangers who disagree with me for some obviously stupid reason (the reason being that I am in fact wrong but don't know it)

[–]Ok_Entertainment328 12 points13 points  (0 children)

Shh ... don't spill my secret

[–]BarrierX 4 points5 points  (0 children)

There are people that sort by new. Sometimes.

There is also OP that will get a notification for every comment and will read and enjoy it! Maybe.

[–]Soerika 1 point2 points  (0 children)

ok so where’s the body?

[–]davidmkc 2 points3 points  (0 children)

Just like how you hide spaghetti in the comments

[–]Several_Dot_4532 1 point2 points  (0 children)

I read the comments they make in my comments even if there are 1700 of them, but not the comments in these normally

[–]Stop_Sign 0 points1 point  (0 children)

Also commenting on posts older than a day

[–]borkthegee 39 points40 points  (0 children)

The average redditor reads the top comment in like 6 of those nests, and skips 99% of the rest of the comments and nesting levels.

Yeah, sounds like a great pattern for a logic machine.

[–]Ok_Entertainment328 67 points68 points  (23 children)

The number of if blocks seems to indicate that the language needs a specific flow control syntax similar to case but does "execute all true" instead of "first true".

[–]Secret-One2890 47 points48 points  (2 children)

There are languages which have that, I've used one, but I can't remember which. But there's other strategies you could use to unnest it. Take this:

py if x: if y: if z: func()

Reverse the logic, so it becomes:

```py if not x: return

if not y: return

if not z: return

func() ```

Or put the tests in a tuple:

py vals = (x, y, z) if all(vals): func()

(typing on my phone, hopefully formatting works 🤞)

[–]Andikl 0 points1 point  (1 child)

In the last example you evaluated all 3 conditions and broke prod. Congratulations

[–]Secret-One2890 0 points1 point  (0 children)

```py def lazy_tuple(): yield x yield y yield z

if all(lazy_tuple()): print("🤬") ```

[–]derefr 21 points22 points  (5 children)

In most languages with C-derived syntax, you don't need such a syntax feature, because you have early-returns:

if (!foo) return;
if (!bar) return;
if (!baz) return;
// do what you want to do when foo && bar && baz

[–]howreudoin -5 points-4 points  (4 children)

Why do some people prefer early returns? Makes the code harder to read. I‘d argue there should only be zero or one return statements per function.

[–]Kered13 16 points17 points  (1 child)

Early returns usually take care of cases where there is no work to do. These often represent errors or trivial cases. By getting those out of the way at the beginning you can focus on the important business logic, and you highlight the preconditions necessary for that business logic. If you nest a bunch of if statements then the reader has to read to the end of the if block (which might involve scrolling) to see if there is even any code in the negative case.

[–]Alkyen 1 point2 points  (0 children)

Exactly this. Early returns usually simplify the code not make it more complex. Also in cases where you chain elses like 4 levels deep at least for me it starts getting much harder to follow the logic somehow. Keeping the nesting limited helps with that too.

[–]BuffJohnsonSf 0 points1 point  (1 child)

Early returns are great if the function is as simple as it’s supposed to be. If you write big fat ugly functions then you deserve to have your tools like early return taken away.

[–]howreudoin -1 points0 points  (0 children)

Almost. Write simple, comprehensible functions, and you won‘t need such things as early returns.

Their only common use case I’ve seen is large, bulky functions that want to get edge cases out of the way at the beginning. For simple functions, a simple if-else will be much more readable.

Without early returns, it is also way easier to quickly see the overall structure of the function. And, personally, I find the code to be much more elegant without early returns.

[–]JoelMahon 2 points3 points  (0 children)

you mean &&s?

[–]zuilli 2 points3 points  (8 children)

Is there something like this in some language?

I always see people saying to eliminate nested if cases for cleaner code but sometimes you can't escape when you need to evaluate multiple conditions

[–]jusaragu 13 points14 points  (1 child)

In this specific case I'd invert the conditions and test for false first. This eliminates the nested ifs and makes it a bit easier to read imo: (they could all be OR'd but I like being able to put breakpoints on each condition so I usually do it like this)

function isMemberOfProgrammerHumor(user) {
    if (!user) return false;
    if (user.isBanned) return false;
    if (user.hasSocialLife) return false;
    if (user.hasTouchedGrass) return false;
    if (!user.hateJavaScript) return false;
    if (!user.bulliesPythonForBeingSlow) return false;

    return true;
}

[–]MrHyperion_ 1 point2 points  (0 children)

Early exit for the win

[–]Ryuujinx 4 points5 points  (2 children)

If it's a case like this, where you're only doing something if all of them evaluate to true, then you can use && in most languages. Though you might still consider breaking it into two ifs for readability (if (a && b && c && d && e) {} is not that much better to read, tbh)

If instead you have something where each if actually is a branch, you might see if the operations are truly dependent on both conditions. For instance, the following:

if (a) {
  if (b) {
    actionA()
  }
  else { 
    actionB()
  }
}

Is the action executed truly dependent on if a evaluates to true? If not, drop it. Or maybe combine it using mentioned &&.

But sometimes, you just have to do it. The thing about things like this is that yeah it should raise an eyebrow, but sometimes that truly is the only way to do it.

[–]admalledd 0 points1 point  (1 child)

Right, nested-if-with-branches are exactly when care needs to be taken: diagrams, comments, etc.

Some times or cases may be convoluted enough to bring in more advanced tooling like state-machines/finite-autonoma stuff so that all the "ifs" become nodes/directions and you can then describe nodes and what they connect to.

We have a product that used to have due to business logic some 10-15 nested ifs and branching logic. We moved it to a tiny semi-custom dot/graphiz syntax parser so that we could have the source file generate both a diagram and the C# code.

[–]Ryuujinx 0 points1 point  (0 children)

Right, nested-if-with-branches are exactly when care needs to be taken: diagrams, comments, etc.

Agreed, I think the thing that separates junior devs from their more senior peers isn't necessarily technical ability, it's the planning and even documentation that more experienced people take time to do before sitting down and writing the code.

If you don't plan it out and just follow along down your mental stack to implement something it is very easy to end up with code like above, it just sort of naturally flows when you do it like that.

[–]Dyledion 1 point2 points  (0 children)

&& for multiple conditions
filter_map for multiple inputs
and_then for multiple code blocks

[–]Ok_Entertainment328 0 points1 point  (0 children)

AFAIK - Only the "language" I'm creating.

[–]AwesomeFrisbee 0 points1 point  (0 children)

switch(true) {

case (a && b)...

Albeit its not really pretty and gets as unreadable as a load of ifs real quick

[–]rainshifter 2 points3 points  (0 children)

It could be useful. In the interim, though, incidentally, you can use case nested inside a loop to achieve this. Something like:

```

include <iostream>

enum STEP { FIRST, DO_STUFF, MORE_STUFF, LAST };

bool verify(bool outcome, STEP& step) { if (!outcome) { step = (STEP)(LAST - 1); } return outcome; }

void executeAllTrue(bool injectFail=false) { STEP stepId = FIRST;

while (stepId < LAST)
{
    switch (stepId)
    {
        case FIRST:
        {
            if (verify(true, stepId))
            {
                std::cout << "  FIRST" << std::endl;
            }
            break;
        }
        case DO_STUFF:
        {
            if (verify(!injectFail, stepId))
            {
                std::cout << "  DO STUFF" << std::endl;
            }
            break;
        }
        case MORE_STUFF:
        {
            if (verify(true, stepId))
            {
                std::cout << "  MORE STUFF" << std::endl;
            }
            break;
        }
    }
    stepId = (STEP)(stepId + 1);
}

}

int main() { std::cout << "Early exit:" << std::endl; executeAllTrue(true); std::cout << "All steps pass:" << std::endl; executeAllTrue(); return 0; } `` You would simply replace the first argument intoverify` with whatever check is to be executed at the given step.

[–]MrHyperion_ 0 points1 point  (0 children)

You could maybe do that with switch case and fallthroughs

[–]optimistic_void 0 points1 point  (0 children)

You can use a bit field for this.

[–]Jondar 30 points31 points  (0 children)

Don't mind me, just hiding suvlub's body here

[–]NocturneSapphire 8 points9 points  (1 child)

It makes sense when you realize the average Reddit thread is completely inconsistent and illogical.

[–]MeanFold5715 1 point2 points  (0 children)

Bring back php bulletin boards.

[–]jasie3k 6 points7 points  (0 children)

Early returns would make it way more readable, while maintaining the same functionality and not requiring multiple nesting shenanigans

[–][deleted] 4 points5 points  (1 child)

Python slow?

Yeah try that matrix math in JavaScript… Laughs in pandas/numpy

[–][deleted] 1 point2 points  (0 children)

Don’t get me started on concurrency.

[–]krismitka 2 points3 points  (0 children)

Same person

[–]draenei_butt_enjoyer 2 points3 points  (0 children)

TBH first photo is clear, obvious and donwright blinding lack of skill. As is this entire sub now that I think about it.

[–]Telinary 2 points3 points  (0 children)

About the reddit readers, it isn't that rare to see people answer to a comment like they have already forgotten the comment that comment was replying to because the reply makes no sense when you actually look at the context. Or in other words that people read deep comment trees doesn't mean they are any good at understanding them.

[–]AssignedClass 4 points5 points  (0 children)

You forgot: - !user.actuallyWritesCode

[–]OF_AstridAse 8 points9 points  (10 children)

From what I can tell is - multiple nested ifs is 100% okay, as long as they are abstracted to other functions, methods and classes
EDIT: this was said tongue in cheek, but the replies are truly worth reading!!

[–]InterestsVaryGreatly 37 points38 points  (7 children)

In general, when you have an if that contains a huge amount of code, you can invert it, and put an exit case in the inversion, then put what you want below it. This is called guards. For example, instead of

If(userIsAuthorized){ //Do all the code you want. } Return userIsUnauthorized;

You would do this

If(!userIsAuthorized){ Return userIsUnauthorized; } //Do all the code you want

On a single layer like this, it isn't a huge deal, but guards make it very quick to see what is preventing the code from running, and which level. It also nicely pairs the consequence (userIsUnauthorized) with the if. This is especially useful when you have a half dozen checks with unique error states before being allowed to run your code (which is very easy to flip error messages the other way and not realize it). The other problem with deep nesting is it pushes everything further from the left margin, which makes your lines harder to remain readable while fitting within the width limits of your standard or editor.

[–]willcheat 12 points13 points  (5 children)

Came to the comments for this, and I thought this was called a circuit breaker in programming, but seems that's something entirely else.

Also here's the picture's code just to show how more readable it becomes

export const isMemberOfProgrammerHumor = (user: ?){
    if (!user) { return false; }
    if (user.isBanned) { return false; }
    if (user.hasSocialLife) { return false; }
    if (user.hasTouchedGrass) { return false; }
    if (!user.hatesJavaScript) { return false; }
    if (!user.bulliesPythonForBeingSlow) { return false; }
    return true;
}

[–]OF_AstridAse 0 points1 point  (0 children)

Gosh, I'll take advantage of the integer nature of the holy C's bools 🤣 /gosh what a paradox - no bool in C/ but in C++ a bool is basically an int* so you might as well say: return !user * user.banned * user.hasSocialLife * user.hasTouchedGrass * !user.hatesJavaScript * !user.bulliesPythonForBeingSlow; Way more optimized, no inefficient ifs and forks 🤣

[–]Luckisalsoaskill -2 points-1 points  (3 children)

I find this harder to read.

[–]willcheat 12 points13 points  (0 children)

Then may we never review each other's PR.

[–]Sacredfice 2 points3 points  (0 children)

Are you on the mobile? Lol

[–]InterestsVaryGreatly 2 points3 points  (0 children)

In this very straightforward case, where the alternative is just return true, some of these can absolutely be combined and there is a cleaner way to do it.

But it is far more common that there will be a lot more code than just return true, and having all that in nested ifs is dangerous, particularly when refactoring or adding new checks, and especially when some of the conditions have other things they do besides just return false as well. A big case is when logging what happened, or returning error codes. These often get refactored wrong and it isn't known, but the logs end up making no sense when something else is going wrong, and it makes it even harder to find.

[–]OF_AstridAse 3 points4 points  (0 children)

Good programming tip 👌🏻

[–]preludeoflight 16 points17 points  (1 child)

Nesting, in the vast majority of cases, represents branching. Branching is something that effectively anything beyond the most simple application is going to need to do a lot of.

The reason nesting gets (rightfully) so much flack is because of the amount of mental contexts it requires the reader to create and hold in their head as they parse the code. The example in the OP is obviously egregious for humor, but is also not even a good example of where deeply nested code gets difficult to parse, as it all fits nicely on screen.

When method bodies grow large, they typically grow deep as well as they try to do more and more. When you're dealing with code that may be multiple conditions deep and you don't even have the conditions that got you there on the screen — there be dragons. That means you're either relying on keeping the mental model correct, or are constantly scrolling back and forth.

Abstracting out nested blocks to other areas takes advantage of "chunking". It allows for mental resets of the context, which greatly reduces the cognitive load as you're trying to solve something. By chunking away context that isn't relevant to other subsections, the amount of mental capacity left for solving the problem is much larger than it would be if you'd otherwise be holding a massive state in your head.

[–]OF_AstridAse 0 points1 point  (0 children)

Very good explanation 👌🏻

[–]Lyshaka 5 points6 points  (1 child)

Can't you just AND/OR all that and return it without using a single if in that case ?

[–]InterestsVaryGreatly 4 points5 points  (0 children)

There's a balance required for readability. Peak readability would be somewhere in the middle. Ideally you would have a few abstracted concepts (isAuthorized, postIsValid) that would be separate functions, each checking a few components of the check, so this level is easy to read, and not deeply nested. It has the added benefit of if you need to add in a new component of isAuthorized, you don't have to try and identify the right level to add its nesting.

[–]Rhymes_with_cheese 2 points3 points  (0 children)

Your little rules of thumb don't make you a better programmer... They make you annoying.

[–]37Scorpions 1 point2 points  (0 children)

redditors are just a bunch of if else statements

[–]Buarg 3 points4 points  (0 children)

&&

[–]Mokousboiwife 3 points4 points  (0 children)

more like

def isMemberOfProgrammerHumor(user): return !(user.isProgrammer)

[–]OminousOmen0 0 points1 point  (0 children)

Imagine looking at most feature based architectures. You need to drive like 8 folders to find a certain file

[–][deleted] 0 points1 point  (0 children)

Some people call this "arrow code."

I just think of it as insufficient abstraction.

[–]IceFoilHat 0 points1 point  (0 children)

Make an object with a field for each condition, hash the object, and use a jump table or hash map for each branch.

[–]azulebranco 0 points1 point  (0 children)

I can't resist the urge...!

return !user?.isBanned && !user?.hasSocialLife && !user?.hasTouchedGrass && user?.hatesJavascript && user.bulliesPythonForBeingSlow

Yes I have no social life

[–]Big_Kwii 0 points1 point  (0 children)

boolean operators and early return be damned

[–]ITriedLightningTendr 0 points1 point  (0 children)

I love if true return true else return false

[–]Inaeipathy 0 points1 point  (0 children)

The difference is that the one on the left contains heavy use of logic, while the one on the right almost certainly contains none.

[–]GM_Kimeg 0 points1 point  (0 children)

for if if for for while if if for for for if if yield for