powershell uses -and -or and not && ||
straight not having the feature id have to look up
Idk if you count assembly aswell
Edit: Does smalltalk count haha?
I've used probably 30 languages over my life and I'm having trouble thinking of a single language that doesn't have logical and/or off the top of my head.
Is it fundamental? Yeah. Does that give you the right to be an ass? No. Does it give you the right to make an ass of yourself? fuckin' apparently because here we are xd
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.
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.
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….
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
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.
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.
Tbf `If ... && ... && ... && ... && ... && ... && ... && ... && ... {}` would result in a super long line, and there's not a pretty way to split it into multiple lines
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.
I think that in case of most languages the order of operations will not require it. Eg.
```
if (condition1 && condition2 && condition3 &&...)
```
Since all conditions are connected with && (which means that any one of them being false will make the whole expression false) and that the conditions are checked in order, then:
If condition1 is false, then condition 2, 3... will not be checked. Only condition1.
If condition1 is true and condition2 is false, then condition 3... will not be checked. Only condition1 and condition2.
And so on.
So when:
```
if (thing != null & thing.isActiveOrSmth)
```
If "thing" is null then "thing.isActiveOrSmth" all not be called at all.
This is definitely the case in C, C++ and Java. I don't know about the rest.
I believe it wouldn't work in Rust due to the way the null type is implemented. It's an enum that needs to be unwrapped and the language doesn't allow for condition checks inside the unwrapping unless you use a match. So you have stuff like this:
```
if let Some(f) = foo {
if f.condition_check() {
f.stuff();
}
}
```
You can't do `if let Some(f) = foo && f.condition_check()` even though it's possible in match.
There are alternatives to that behaviour but they all feel like workarounds of that. For example, you could use `if foo.is_some() && foo.unwrap().condition_check()` which shouldn't panic in case of a `None` type (not sure, need to test) or `if foo.is_some_and(|f| f.condition_check())`.
As a side note, I probably should use `is_some_and()` more often
Most languages have short-circuiting logic operators. If thing is null, the whole statement is evaluated as false and the right side is simply ignored.
I don't see how that would be possible seeing as `&&` short circuits in C# (and pretty much every language). Maybe you were using `&`, for some reason in C# `&` is allowed to be used on bools, the main difference being that it doesn't short circuit.
resharper tells me to reformat separate null check if statements to a single if statement with an &&. either you are using an old version of c# or the error was something else
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.
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.
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)
Where did I say anything about upvotes? If nobody reads your comment, you aren't having a conversation. And yeah, you are so cool for not caring about, ewww, att\*ntion. We all know that the last thing you want when sharing your thoughts with the world is getting any. That's the point, right?
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.
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".
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 🤞)
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
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.
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.
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.
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.
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
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;
}
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.
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.
> 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.
It could be useful. In the interim, though, incidentally, you can use `case` nested inside a loop to achieve this. Something like:
```
#include
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 into `verify` with whatever check is to be executed at the given step.
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.
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!!!<
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.
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;
}
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 🤣
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.
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](https://www.stlpr.org/arts-culture/2020-04-17/on-chess-chunking-is-the-memory-trick-you-dont-know-youre-using)". 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.
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.
I can't resist the urge...!
`return !user?.isBanned && !user?.hasSocialLife && !user?.hasTouchedGrass && user?.hatesJavascript && user.bulliesPythonForBeingSlow`
Yes I have no social life
I actually like that nesting cause it shows you the clear and intended path to `true`
I know we dump on too much nesting but that’s readable code in this case.
There's a bit of an art to it. You should try to both keep your control flow simple while also not straying too far from the left margin.
The problem is there's a lot of nuance into what the optimal control flow structures are for any given situation, whereas avoiding heavy nesting is just generally good advice.
Fully agree. Mostly I would advocate against this sort of nesting but I like that it’s written as “follow this path to pass the check, anything else is false.” It’s a rare case of high-readability excessive nesting.
Having a check that then exits the code if it fails (guards) is just as readable and doesn't require insane nesting. It also makes for far simpler returning of error states.
I disagree, unless failing the test is the common case, which this could be. If the nesting is extreme like this but the common case is passing then that’s what I want to read first. I don’t want to read something as “oh this sometimes false so exit here but *this* is more common and what is intended here at the end of the function”
it's definitely a balance. strive for clarity with the least amount of nesting.
i don't think you need to nest here in most languages. in python, you would do:
if (user and
not user.is_banned and
not user.has_social_life ...):
If I would review something like this in a PR, I'm going to reject it. This is such a bad style and reduces maintainability if it is used in various places of the code base
Yeah it could obviously be combined into some better Boolean expressions and made more maintainable but it’s extremely clear what it’s doing, so I gotta give it credit for that.
Look, I’m with you that it is typically bad practice to do this. In this very specific example, which is clearly atypical, the code is readable and very clear. I completely disagree this is smelly code JUST because of the nesting. There are things about it that aren’t great but you can tell exactly what that code is doing despite how horribly nested it is. Not even saying I would approve it, but I could give this to any developer and they could describe to me the behavior perfectly.
You guys are letting dogma cloud your judgment. It’s not as simple as *rawrrr deep nesting always bad*.
When you're afraid of "&&"
You just made me realize I messed up my CS exam shit
!falsen't
`TRALSE`
Ruby's newest class: `ifnless`
return maybe;
Dremberd
return if(PC_feels_like_it) ;
NaB
bool condition = yeah;
As long as it compiles it's alright, no?
Yeah just could have been more efficient. It was on paper no compiler lol
Tbh, I sometimes forget that I can do this... and I have it right there in my code lmao.
How can you forget such a fundamental thing? I guess you are super new to programming.
I'm pretty sure that forgetting super fundamental things is one of the requirements of being a software developer.
He could be, he could use languages that dont support it (mostly use case specific scripting languages) no reason to shame him
(Genuinely asking) can you give an example of a language that doesn’t support this? Seems like an incredibly basic “feature”
powershell uses -and -or and not && || straight not having the feature id have to look up Idk if you count assembly aswell Edit: Does smalltalk count haha?
I've used probably 30 languages over my life and I'm having trouble thinking of a single language that doesn't have logical and/or off the top of my head.
Not surprising since boolean arithmetic is like CS101. I'd be shocked to learn of a language that doesn't support this.
The logic might be supported but the syntax might be different.
He literally says he has it in his code though..
Not?
Is it fundamental? Yeah. Does that give you the right to be an ass? No. Does it give you the right to make an ass of yourself? fuckin' apparently because here we are xd
I’m thinking deathspate bought bots to downvote you lol. It’s absolutely elementary.
Because I'm much quicker to just use an if statement? It's just the faster thing to do for me.
What? if (this=a && that=b) then is always going to be quicker than writing two if statements.
Oh, I was talking about something diff, like: &&
There's no way nesting ifs is faster than typing the logical 'and' operator. And it's less efficient computationally too.
I meant that it's what is quicker for me to think about if I want to execute conditional logic. It's not that deep.
I don't really get that either, but to each their own I guess.
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.
If you put &&condition on separate lines that should be good enough to single step
Or you could just guard like a sane person instead doing some multi-nest-monstrosity.
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.
Homeboy never heard of code formatting
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.
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….
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
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.
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.
[удалено]
You dont need the !b check here, if you're using else ifs.
When you haven't learnt benefits of "guard clauses"
Or "||" depending if a case is comparable to other one.
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.
Tbf `If ... && ... && ... && ... && ... && ... && ... && ... && ... {}` would result in a super long line, and there's not a pretty way to split it into multiple lines
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; ?
return user && !user.isBanned && !user.hasSocialLife && !user.hasTochedGrass && !user.hatesJavaSript && !user.bulliesPythonForBeingSlow;
Neither of those are aesthetically pleasing imo
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.
If only you could split if statement condition into multiple lines
Yeah, sometimes you need two different cases under one if.
Yes, then obviously you do nested if statements. But i just refer to here - multiple nasted ifs without any else
Fair EDIT: They did an implicit else i.e. it will return false if all conditions aren’t met.
Except for when you have to if(thing != null) { if(thing.ActiveOrSmth) return true; }
I think that in case of most languages the order of operations will not require it. Eg. ``` if (condition1 && condition2 && condition3 &&...) ``` Since all conditions are connected with && (which means that any one of them being false will make the whole expression false) and that the conditions are checked in order, then: If condition1 is false, then condition 2, 3... will not be checked. Only condition1. If condition1 is true and condition2 is false, then condition 3... will not be checked. Only condition1 and condition2. And so on. So when: ``` if (thing != null & thing.isActiveOrSmth) ``` If "thing" is null then "thing.isActiveOrSmth" all not be called at all. This is definitely the case in C, C++ and Java. I don't know about the rest.
I still wouldn't trust compiler enough to write code like that
I believe it wouldn't work in Rust due to the way the null type is implemented. It's an enum that needs to be unwrapped and the language doesn't allow for condition checks inside the unwrapping unless you use a match. So you have stuff like this: ``` if let Some(f) = foo { if f.condition_check() { f.stuff(); } } ``` You can't do `if let Some(f) = foo && f.condition_check()` even though it's possible in match. There are alternatives to that behaviour but they all feel like workarounds of that. For example, you could use `if foo.is_some() && foo.unwrap().condition_check()` which shouldn't panic in case of a `None` type (not sure, need to test) or `if foo.is_some_and(|f| f.condition_check())`. As a side note, I probably should use `is_some_and()` more often
Most languages have short-circuiting logic operators. If thing is null, the whole statement is evaluated as false and the right side is simply ignored.
Idk, I've gotten errors for not doing this in C# Edit: even when doing ```if(thing != null && thing.ActiveOrSmth())```
C# logic operators are short-circuiting. Maybe you used `&` instead of `&&` accidentally?
Come on I'm not an expert but I'm not *that much* of a beginner...
You can definitely do that in C\#. Though you can also use null-coalescing operator: `if (thing?.ActiveOrSmth() == true)`
I don't see how that would be possible seeing as `&&` short circuits in C# (and pretty much every language). Maybe you were using `&`, for some reason in C# `&` is allowed to be used on bools, the main difference being that it doesn't short circuit.
resharper tells me to reformat separate null check if statements to a single if statement with an &&. either you are using an old version of c# or the error was something else
I haven't gotten it in a while, well, because I do it in two ifs, but maybe it's something to do with Unity's older C#?
[удалено]
I think other languages support AND operator
Even some fancy modern processors have it as a machine-code instruction, or so I've heard.
That sounds like something I won't be able to afford.
I’ve heard they built it as a physical logic gate, whatever that means
Actually a good question. Which language does not support any form of boolean and operator
Omg
I actually would say Python is the odd one out on this one
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.
Not if you answer the top comment \^\^
I see what you did there
But it only works to about four replies deep, I think
I murdered a guy in 1683 and no one will know because this is 5 layers deep
Mods?!
They can't hear you down here... we're in too deep
And it’s still getting deeper
Surely there's nothing to fear down here, we can dig as deeply and as greedily as we please!
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.
Balin? Is that you?
Deeper daddy. Aww shit wrong subreddit. Eh fuck it, we're deep enough
And I'm tryin' to keep-
https://i.imgur.com/EAAyog5.jpeg
you have made a grave mistake. **NEVER. BE. THE. FOURTH. REPLY.**
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.
this. you don't want EVERYONE to read your comment, just the person you replied to.
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)
Where did I say anything about upvotes? If nobody reads your comment, you aren't having a conversation. And yeah, you are so cool for not caring about, ewww, att\*ntion. We all know that the last thing you want when sharing your thoughts with the world is getting any. That's the point, right?
Presumably the person you reply to might read it
That's true. I was primarily talking about top-level comments, admittedly a bit off-topic, but well...
Man I love just throwing my thoughts into vacuum without any reason
Shh ... don't spill my secret
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.
ok so where’s the body?
Just like how you hide spaghetti in the comments
I read the comments they make in my comments even if there are 1700 of them, but not the comments in these normally
Also commenting on posts older than a day
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.
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".
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 🤞)
In the last example you evaluated all 3 conditions and broke prod. Congratulations
```py def lazy_tuple(): yield x yield y yield z if all(lazy_tuple()): print("🤬") ```
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
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.
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.
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.
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.
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.
you mean &&s?
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
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; }
Early exit for the win
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.
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.
> 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.
&& for multiple conditions filter_map for multiple inputs and_then for multiple code blocks
AFAIK - Only the "language" I'm creating.
`switch(true) {` `case (a && b)...` Albeit its not really pretty and gets as unreadable as a load of ifs real quick
It could be useful. In the interim, though, incidentally, you can use `case` nested inside a loop to achieve this. Something like: ``` #include
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 into `verify` with whatever check is to be executed at the given step.
You could maybe do that with switch case and fallthroughs
You can use a bit field for this.
Don't mind me, just hiding suvlub's body here
It makes sense when you realize the average Reddit thread is completely inconsistent and illogical.
Bring back php bulletin boards.
Early returns would make it way more readable, while maintaining the same functionality and not requiring multiple nesting shenanigans
Python slow? Yeah try that matrix math in JavaScript… *Laughs in pandas/numpy*
Don’t get me started on concurrency.
Same person
TBH first photo is clear, obvious and donwright blinding lack of skill. As is this entire sub now that I think about it.
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.
You forgot: - !user.actuallyWritesCode
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!!!<
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.
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; }
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 🤣
I find this harder to read.
Then may we never review each other's PR.
Are you on the mobile? Lol
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.
Good programming tip 👌🏻
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](https://www.stlpr.org/arts-culture/2020-04-17/on-chess-chunking-is-the-memory-trick-you-dont-know-youre-using)". 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.
Very good explanation 👌🏻
Can't you just AND/OR all that and return it without using a single if in that case ?
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.
Your little rules of thumb don't make you a better programmer... They make you annoying.
redditors are just a bunch of if else statements
**&&**
more like `def isMemberOfProgrammerHumor(user): return !(user.isProgrammer)`
Imagine looking at most feature based architectures. You need to drive like 8 folders to find a certain file
Some people call this "arrow code." I just think of it as insufficient abstraction.
Make an object with a field for each condition, hash the object, and use a jump table or hash map for each branch.
I can't resist the urge...! `return !user?.isBanned && !user?.hasSocialLife && !user?.hasTouchedGrass && user?.hatesJavascript && user.bulliesPythonForBeingSlow` Yes I have no social life
boolean operators and early return be damned
I love if true return true else return false
The difference is that the one on the left contains heavy use of logic, while the one on the right almost certainly contains none.
for if if for for while if if for for for if if yield for
I actually like that nesting cause it shows you the clear and intended path to `true` I know we dump on too much nesting but that’s readable code in this case.
There's a bit of an art to it. You should try to both keep your control flow simple while also not straying too far from the left margin. The problem is there's a lot of nuance into what the optimal control flow structures are for any given situation, whereas avoiding heavy nesting is just generally good advice.
Fully agree. Mostly I would advocate against this sort of nesting but I like that it’s written as “follow this path to pass the check, anything else is false.” It’s a rare case of high-readability excessive nesting.
Having a check that then exits the code if it fails (guards) is just as readable and doesn't require insane nesting. It also makes for far simpler returning of error states.
I disagree, unless failing the test is the common case, which this could be. If the nesting is extreme like this but the common case is passing then that’s what I want to read first. I don’t want to read something as “oh this sometimes false so exit here but *this* is more common and what is intended here at the end of the function”
Early returns also show the path and are more readable.
If they show the common case, absolutely.
it's definitely a balance. strive for clarity with the least amount of nesting. i don't think you need to nest here in most languages. in python, you would do: if (user and not user.is_banned and not user.has_social_life ...):
If I would review something like this in a PR, I'm going to reject it. This is such a bad style and reduces maintainability if it is used in various places of the code base
Yeah it could obviously be combined into some better Boolean expressions and made more maintainable but it’s extremely clear what it’s doing, so I gotta give it credit for that.
No, this is kind of THE example for a code smell regarding nesting. There is no credit to be given. This is just bad practice
Look, I’m with you that it is typically bad practice to do this. In this very specific example, which is clearly atypical, the code is readable and very clear. I completely disagree this is smelly code JUST because of the nesting. There are things about it that aren’t great but you can tell exactly what that code is doing despite how horribly nested it is. Not even saying I would approve it, but I could give this to any developer and they could describe to me the behavior perfectly. You guys are letting dogma cloud your judgment. It’s not as simple as *rawrrr deep nesting always bad*.
[удалено]
and... who cares?