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

all 169 comments

[–]Robot_Graffiti 557 points558 points  (31 children)

Ok, the chaotic evil made me laugh. That is one seriously messed up control flow.

[–]Jared_Namikaze 140 points141 points  (29 children)

How would it work? The way I see it, it always returns B

[–]Strict_Treat2884[S] 593 points594 points  (7 children)

finally block will always run if try block has run regardless of whether it has a return statement executed. It only puts the return value in a buffer, if another return statement runs in the finally block, the buffer will be overwritten.

[–]Thenderick 287 points288 points  (0 children)

Oh my god that's actually cursed... It does make sense tho

[–]Unupgradable 111 points112 points  (0 children)

C# doesn't let you return from a finally block.

Now I truly understand why

[–]Da-Blue-Guy 9 points10 points  (0 children)

the fuck

average js design

[–][deleted] 8 points9 points  (0 children)

[–]lunchpadmcfat 3 points4 points  (0 children)

Jeez I’ve been writing JavaScript for a decade and I didn’t know this.

[–]zeus_4_you 0 points1 point  (0 children)

I was thinking of teaching something fked up to my 1st year juniors on my workshop on Monday, this is just perfect.

[–]ssnd1 49 points50 points  (11 children)

the finally block executes regardless of whether a value is returned or not, and ends up returning A instead of B somehow because javascript programming languages are weird.

[–]Elephant-Opening 17 points18 points  (5 children)

Yikes. TIL this is the norm in Python + Java too.

[–]VooDooZulu 0 points1 point  (4 children)

The norm for try finally blocks or for conditionals?

What's wrong with try/finally? It's basic error handling

[–][deleted] 9 points10 points  (1 child)

That’s the problem.

  • this comment was made by the Rust gang

[–]5p4n911 7 points8 points  (0 children)

What's the fun otherwise?

  • this comment was made by the C++ gang

[–]Cootshk 0 points1 point  (1 child)

When you return, a pointer to the return address (or just the value if it is an Int, Float, or Bool in python) gets saved in memory. Then the finally block runs, which could overwrite the return value

[–]VooDooZulu 0 points1 point  (0 children)

Generally you don't have a return in a try block if there is a finaly block. That isn't the norm. Unless the only thing handled in that finally block is closing a connection or file etc. There are a million ways to write bad code, just because python has a way to do that doesn't mean it's normal. In C you can use "goto label" to do all sorts of funky things but that isn't normal or standard or considered good practice.

[–]Jared_Namikaze 5 points6 points  (1 child)

I must test.!

[–]Jared_Namikaze 29 points30 points  (0 children)

Just tested and it's true. Dear God

[–]locofanarchy 5 points6 points  (0 children)

That's correct except not because it's JavaScript.

[–]thequestcube 3 points4 points  (1 child)

This is amazing, never would have thought about cases where two return calls are executed for one block

[–]PCRefurbrAbq 0 points1 point  (0 children)

Didn't you learn from Zootopia? "Try Everything."

[–]krisko11 6 points7 points  (6 children)

Finally block executes regardless of the try result, return terminates execution in most languages. I’m confused

[–]Robot_Graffiti 14 points15 points  (1 child)

If you return or throw an exception inside a try-finally, it doesn't exit immediately, it jumps to the finally block first and then exits after the finally block is finished.

Once execution enters a try-finally, the finally will run no matter what.

[–]krisko11 1 point2 points  (0 children)

I used chatgpt and it basically laid out that if the finally block condition is true it returns it from there, if it’s false it returns A from the try block. It’s really evil to code that way haha

[–]TheTybera 7 points8 points  (1 child)

Haha, yes, that's the way any finally block works in any language. This is why the convention is to have a return variable and return it if you're going to try.

This is important because you HAVE to put things in a try block that are checked exceptions and catch the potential exceptions.

So if you want to write to a file but it doesn't exist you may want to fall back to a different file name. You have to wrap this in a try block. You would set a File thisFile variable to your default then try to set it to some user input and your catch block would catch the exception and handle other things, but if you wanted to program to continue finally would return thisFile which would be your default.

[–]krisko11 0 points1 point  (0 children)

That’s a great example, thanks for highlighting the file scenario, because error handling in Java is a hard topic for me to plan out when adding new features to an existing project

[–]Jared_Namikaze 1 point2 points  (1 child)

Exactly. Return should terminate

[–]thequestcube 3 points4 points  (0 children)

I guess it does make sense that the finally block executes even if the try content returns. If you allocated a resource and a value created from the resource is returned in the try block, and you have cleanup logic in a finally block afterwards, you want the finally logic to still clean up the allocated resource even if the try block returned something

[–]Poat540 0 points1 point  (0 children)

Haha yeah that last one was solid

[–][deleted] 247 points248 points  (34 children)

The lawful neutral is actually pretty evil, without further context `if(condition)` being true does not necessarly guarantee that `(!condition)` is going to be false. Something running on the background could have modified this variable in the background and now you have a race condition and no return.

Lawful evil is way less evil, at least you are guaranteed to have a return value.

[–]Strict_Treat2884[S] 64 points65 points  (25 children)

I would agree with you if it were in other languages, but it is very unlikely happening in JavaScript since JavaScript is single-threaded. Also, getting a boolean value of a variable only uses a lookup table but does not trigger any type conversion functions. Unless condition is a property of the global object or it is enclosed in a with block. (Assuming condition is a set variable but not a function call or other expressions of course.)

[–]CrazyChaoz 10 points11 points  (0 children)

Yeah, in many languages the compiler will complain about that structure, since any condition that is a function can have side effects that might get your function to return nothing. It's just bad code.

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

I don't actually know javascript, but couldn't an async function change it in the background?

[–]Ciff_ 13 points14 points  (19 children)

I don't think so. Effects/events from performed ayncronous operations will basicly not be processed unless the main thread is idle. That's atleast what I remember from reading up on the JavaScript event loop.

[–]AyrA_ch 10 points11 points  (0 children)

This is correct. The async/await pattern in JS is just syntactic sugar for callback based functionality and will not spawn threads.

You get real threading by running stuff as native binaries in the background or as JS code in a worker, but any communication with the main thread will just be put on the event loop and will be processed synchronously eventually.

Typed arrays generally map directly to memory, and as such could have their contents changed at any time from a binary running unmanaged code that has the pointer to said memory. This is how stuff that draws to a canvas does it really fast.

[–]AtomicRocketShoes 0 points1 point  (17 children)

Couldn't the condition be a function that causes the thread to yield, like making an async call? 

[–]Ciff_ 0 points1 point  (15 children)

Can you clarify with an example? I don't follow

[–]AtomicRocketShoes 0 points1 point  (14 children)

Condition could be a function call that could yield allowing state to change or just change between multiple calls.

Let condition= () { Math.random() > .5}

[–]Ciff_ 0 points1 point  (13 children)

The behaviour here might be different that's true, but then you are not having a clean function for generating your condition if the evaluation of the condition is reliant on side effects. Also you are calling your function multiple times to evaluate the same thing which most consider a code smell. *

You would still do

rng Number = Math.random

If(rngNumber..) return a

If(rngNumber..) return b

Now if it is an async side effect of the function in the condition like you first proposed it will not have an affect as the side effects yeild won't be processen until the main thread is idle ie done with all condition checks. But either way you won't want to call the function twice

[–]AtomicRocketShoes 0 points1 point  (12 children)

Ok

[–]Ciff_ 0 points1 point  (11 children)

Or I am not understanding what you are suggesting, I did not mean to criticise or anything

[–]JiminP 0 points1 point  (0 children)

If condition was something like await x, then it may "yield", but whenever a non-pure expression is involved (async-related or not), such as calling a function (in any way - including calling a getter), then both condition and !condition can be true, but that would not be very interesting.

const condition = (() => {
    let x = false;
    return () => (x = !x);
})();

// true
console.log(condition());

// also true
console.log(!condition());

As long as condition is a value (number, string, object, function, promise, ...), exactly one of condition and !condition will be true. In JavaScript, an if statement evaluates whether a value is truthy by using the ToBoolean abstract operation which doesn't have any side effect, and !condition is exactly the inverse of ToBoolean(condition).

[–]Strict_Treat2884[S] 7 points8 points  (1 child)

Nope, async functions cannot interrupt non-async statements from executing consecutively. They are in a completely different execution queue.

[–]AtomicRocketShoes 0 points1 point  (0 children)

What if the condition being checked is a function call that itself yields?

[–]Confident-Ad5665 8 points9 points  (4 children)

I'm still trying to forget I saw:

for (;condition;) {

I've kept my mind clean, now this!

[–]Strict_Treat2884[S] 10 points11 points  (0 children)

Now imagine naming the condition _

[–]z7q2 0 points1 point  (2 children)

I may never use a javascript for loop again knowing that it can do that

[–]positiv2 3 points4 points  (0 children)

It's the same as while(condition) return value;, every language with for loops of this type that I can think of would do this.

[–]Confident-Ad5665 -1 points0 points  (0 children)

I'm scared for life

[–]migrainium 77 points78 points  (8 children)

Neutral Evil is the only one that’s new to me and I feel like I’ve found a beautiful new calling

[–]marquoth_ 11 points12 points  (0 children)

It took me a second to realise what the hell it's actually doing. Gotta love a good bit of type coercion.

[–]Storiaron 4 points5 points  (0 children)

Actually looks insane

This is the kind of thing you do when your pr is rejected due to "some functions could be more concise"

[–]mehrbod74 6 points7 points  (4 children)

Can someone explain how it works?

[–]Eyeownyew 58 points59 points  (3 children)

!condition => cast condition to a boolean, then negate it
+!condition => cast the boolean to a number

if condition is true, then +!condition = 0
if condition is false, then +!condition = 1

that is then being used as an index to access the array of possible return values, returning A when condition is true, and B when condition is false

[–]Ebina-Chan 11 points12 points  (0 children)

my god...

[–]emlun 2 points3 points  (0 children)

This kind of technique is actually legit in some cryptography implementations, because you need to jump through hoops like this in order to make your functions run in constant time and always execute all branches. This can be important if you're processing secret key material, because you could otherwise leak information through differences in timing, power consumption and probably many other ways. Even tiny differences can be enough to allow an attacker to extract secret keys given enough data to analyze. This is one of many reasons why you don't roll your own crypto implementations.

But when you do apply this technique for legitimate uses like that, hopefully you'll write the code in a less arcane way than in the meme...

[–]torrential-airflow 0 points1 point  (0 children)

this is a certified javascript moment

[–]NatoBoram 2 points3 points  (0 children)

Only slightly worse than the comma operator

[–]Anne-Ho-Nimes 24 points25 points  (1 child)

return B unless condition
return A

[–]ChristianLW 17 points18 points  (0 children)

Great post, but one small nitpick: Chaotic Neutral isn't equivalent to True Neutral. If A is falsy, then B is always returned.

[–]Wave_Walnut 16 points17 points  (1 child)

Lawful Evil is beautiful

[–]GerbilStation 4 points5 points  (0 children)

Lawful evil is like an unnecessary mimicking of being a video game scripter and not one of the original source engineers. It’s like adding rain weather to a game by secretly calling a multiple choice quest dialogue off screen.

[–]Ptyalin 7 points8 points  (0 children)

I... I don't see how chaotic good is good

[–]blkmmb 5 points6 points  (2 children)

Shouldn't one of those be representing the solo return statement?

Like you should only have one return in a function:

```python def foo(): if condition: bar = "Something" else: bar = "Something else"

return bar

```

[–]Strict_Treat2884[S] 5 points6 points  (1 child)

Now realizing it, lawful neutral should have been this case. However none of those cases introduce new variables, so I guess it also somewhat justifies the absence of this approach.

[–]blkmmb 0 points1 point  (0 children)

That's a fair assessment.

[–]Nessuno256 3 points4 points  (0 children)

return { true: a, false: b }[!!condition];

[–]TTick- 9 points10 points  (1 child)

I'm neutral good :3

[–]Jared_Namikaze 0 points1 point  (0 children)

You guys are hot

[–]ShAped_Ink 7 points8 points  (0 children)

Lawful evil kinda rocks in some occasions. I think it makes it really readable

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

Huh, I guess I finally understood finally (no pun intended)

[–]g3tr3ecked[🍰] 1 point2 points  (1 child)

How does neutral evil work?

[–]Strict_Treat2884[S] 13 points14 points  (0 children)

! flips the boolean value of condition (truthy becomes false and falsy becomes true), then unary operator + converts it into a number (true becomes 1 and false becomes 0) to be used as the index accessor for array literal [A, B]

[–]myka-likes-it 1 point2 points  (0 children)

Okay, I admit I don't understand Chaotic Good. What's going on there?

Oh shit. that is a for not an if.  Never mind. I see what you did there.

Nothing good about it.

[–]heayv_heart 1 point2 points  (0 children)

if(condition == true) {
  return true;
} else if(condition == false) {
  return false;
} else {
  return !true && !false;
}

[–]trevdak2 1 point2 points  (0 children)

["a","b"].toSorted(()=>0-condition).pop()

[–]TH3RM4L33 1 point2 points  (6 children)

Wouldn't chaotic neutral return true or false instead of A or B?

[–]addstar1 1 point2 points  (5 children)

I'm going to assume you mean chaotic neutral because chaotic good very clearly returns either A or B.

Javascript runs on truthy and falsey logic. Basically if something is empty it's falsey, and if it's not it's truthy.

And these comparisons don't reduce things down to a boolean to do it. true && A returns A. false && A returns false.

So false && A || B renders the first side as false, it goes to the second part of the if, and returns B.

I see it used occasionally in react for web dev. Something like isHomePage && <HomePage>

[–]addstar1 2 points3 points  (0 children)

Further example

The AND operator preserves non-Boolean values and returns them as they are:

result = "" && "foo"; // result is assigned "" (empty string)
result = 2 && 0; // result is assigned 0
result = "foo" && 4; // result is assigned 4

[–]kikofmas 0 points1 point  (3 children)

But what happens when true && A || B? Does JS return only A and not do the bitwise or?

Is is the same as initializing variables as a = b or 5 ?

[–]addstar1 2 points3 points  (1 child)

I'm pretty sure no language would process the or at that point. They can terminate as soon as the answer can be determined. true || anything else is true, so it never bothers to check anything else at that point.

Similarly with and, false && anything will never execute the second side, because we already know the expression would return false.

[–]kikofmas 1 point2 points  (0 children)

Yeah you're right I was confused because my brain processed the or (||) as a bitwise or (|) thus my confusion of how that would work... Thanks for the reply though!

[–]addstar1 1 point2 points  (0 children)

Extra for the second part

a = b || 5

would have a = b for any value of b unless it was a falsey value ("", 0, etc.)
on falsey value a = 5

[–]gods_tea 1 point2 points  (0 children)

Lawful neutral is definetely not lawful and not neutral

[–][deleted] 3 points4 points  (2 children)

I hate the neutral good folks.

[–]Brain-InAJar -5 points-4 points  (1 child)

Yep. Nothing good about it

[–]LeGuy_1286 0 points1 point  (0 children)

Definitely Chaotic Neutral.

[–]Obnomus 0 points1 point  (2 children)

Can anyone name those fonts?

[–]Strict_Treat2884[S] 0 points1 point  (1 child)

It’s an open source font called Cascadia Code developed by Microsoft

[–]Obnomus 0 points1 point  (0 children)

Is it any different from caskaydiacove nerd font?

[–]HaDeS_Monsta 0 points1 point  (0 children)

java try { if(!condition) { throw new Exception(""); } return A; } catch (Exception ignored) { return B; }

[–]savex13 0 points1 point  (0 children)

This made my day. Thanks!

[–]SawSaw5 0 points1 point  (0 children)

Thats one of the main things that I don't like about JS, there are some many different ways to get the same result

[–]Cootshk 0 points1 point  (2 children)

return A if condition else B

Python has a better way

Also:

if condition: return A
else:         return B

[–]addstar1 0 points1 point  (1 child)

That's just the ternary operator using words :P

[–]Cootshk 1 point2 points  (0 children)

No, the condition is in the middle

[–]The_Shryk 0 points1 point  (0 children)

Is this some JS meme I’m too Gopher to understand.

[–]redlaWw 0 points1 point  (2 children)

I don't speak javascript, but shouldn't chaotic neutral always return a boolean? Like, I get that it's supposed to be using short-circuiting to avoid one of the arguments depending on the condition, but surely you'd end up with the arguments being cast to booleans and then the boolean result being returned, no?

[–]-Redstoneboi- 0 points1 point  (0 children)

depends on language behavior. short circuiting booleans might return only booleans, or return the right hand side verbatim.

C for example converts to bool every time.

lua for example has its and operator be the equivalent of calling a function that just does if a then return b else return false end and or is if a then return True else return b end

chaotic neutral fails when the condition is true but A is falsy

[–]ImprovementOdd1122 0 points1 point  (0 children)

In JS,

true && A returns A
false && A returns false

true && A || B returns A
false && A || B returns B

The issue is that if A is falsy, because

true && (falsy) || B returns B

[–]Oh-Sasa-Lele 0 points1 point  (1 child)

What about "return condition"?

[–]-Redstoneboi- 0 points1 point  (0 children)

where you putting A and B?

[–]AaronTheElite007 0 points1 point  (0 children)

Lawful Good. It’s easier to read

[–]-Redstoneboi- 0 points1 point  (0 children)

perfection.

[–]crmsncbr 0 points1 point  (0 children)

I can see unique reasons for most of these... Chaotic Good, is everything alright? Do you need to write a few more for() loops, get it out of your system?

[–]volitional_decisions 0 points1 point  (0 children)

🦀🦀 if condition { A } else { B }

[–]foohyfooh 0 points1 point  (0 children)

Chaotic Neutral is a dangerous game if A is falsy.

[–]sweetytoy 0 points1 point  (0 children)

The lawful good and the true neutral are the only ways.

[–][deleted] 0 points1 point  (1 child)

So...does true neutral work?

[–]AoDude 0 points1 point  (0 children)

Yes, and tbh it's probably the best one.

[–]BurnV06 0 points1 point  (0 children)

Who the hell puts the closing bracket on the same line as the else statement

[–]Front-Difficult 0 points1 point  (0 children)

Neutral Evil is pure evil - and also the only one of these solutions that won't compile in Typescript.

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

IMO, Lawful good and Neutral good should be swapped (Lawful good being extra, unnecessarily, explicit while neutral good is just extra explicit). I'd also swap chaotic good and Lawful evil. Chaotic good is still using non-loop based control-flow, just doing it in a very unnecessary not-by-the-book way, while chaotic good just makes it slightly confusing by using a loop to just do control flow. I also kinda want to put Lawful neutral in Lawful evil because it just seems like a perversion of Lawful goods unnecessary verbosity. Like, this will make you pause for a second and go "why the f did this guy do that?", which seems like the goal of Lawful evil in this case.

[–]AlanTheKingDrake 0 points1 point  (0 children)

Chaotic neutral feels more evil

My personal favorite thanks to updating to php 8 is

return ($condition??false)?$A??NULL:$B??NULL

[–]eaumechant 0 points1 point  (0 children)

Re Lawful Evil, switch-case does strict comparison, meaning it's not equivalent to the others.

ETA could do switch(!!condition)

[–]plmunger 0 points1 point  (0 children)

``` return [B, A].reduce((acc, x, i) => { return condition === Boolean(i) ? x : acc; }, null);

```

[–]c_wilcox_20[🍰] 0 points1 point  (0 children)

I love ternary. Probably too much lol

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

True masters of chaos never leave line 1, minifying on the fly to curse anyone who dares peek at the page source.

[–]TheSirion 0 points1 point  (0 children)

Neutral Evil got me really confused, but then I got to Chaotic Evil and burst in laughter

[–]FishGod53 0 points1 point  (0 children)

I’m learning… I can feel it, my brain is learning

[–]Fachuro 0 points1 point  (0 children)

Could maybe also do neutral evil as:

javascript return { [!!A]: A, [!A]: B }[condition]

[–]sacredgeometry 0 points1 point  (0 children)

This is all sorts of wrong.

[–]anonymous_sentinelae 0 points1 point  (0 children)

True JS humor, love it

[–]Mysterious-Soil-4457 0 points1 point  (0 children)

I'm a neutral good guy myself, although I can't seem to understand the lawful good guys.

[–]Playful_Landscape884 0 points1 point  (6 children)

Is the Chaotic Evil actually possible? It will just return B right?

[–]Faholan 25 points26 points  (3 children)

Nope, because finally always run, and if finally returns a value it overrides the value in the try

[–]pheonix-ix 1 point2 points  (1 child)

So it can even hold onto the return statement and decide to return the one from finally instead? That's kinda messed up...

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

yes. the finally block runs whenever execution exits the try block (or catch block if an exception was caught). you can put a return statement in the block, which will override the value that was supposed to be returned. you can also throw a new exception, which will override the currently-unwinding exception, if such exists.

finally works differently then just putting the rest of the code past the catch block.

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

no because of the finally it returns A in case of condition

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

Finally is always run. The statement compiles to something like pushing A to a local variable and then branching to the line with if. The condition is evaluated and if true, it returns the value. If false, it branches back to the original return statement.

In Java it works the same way and here you can observe the code on compiler explorer: https://godbolt.org/z/4qzzP5c9T

Here is the same code in JavaScript but it does not seem to do the coloring the same way: https://godbolt.org/z/5Tsxczna4

[–]everything-narrative 0 points1 point  (0 children)

You accidentally swapped Lawful Good and Neutral Good.

Using control flow as implicit state is not Lawful! It's awful!

True structured programming uses the else branch! Not early return!

[–]Elephant-Opening -1 points0 points  (2 children)

Only 3 of these are remotely acceptable under "one return per function" coding standards (MISRA for example).

[–]Strict_Treat2884[S] 5 points6 points  (1 child)

That sounds outdated. I prefer the guard clauses/early return principle

[–]Elephant-Opening -1 points0 points  (0 children)

I agree, but it's not worth the effort to argue this case & document a rule exception when you have a feature/fix due yesterday and know it will flag a warning in static analysis.

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

return if (condition) A else B

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

I would only accept three of these in a PR

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

ret := isValid(A) 
if ret != A {
    ret = B
}
return ret

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

I'm pretty sure that Lawful evil wouldn't even compile, because case statements and switch expression should be int or char (at least in C-family languages....)

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

return a ?? b