DEV Community

Cover image for If-Else or Switch-Case: Which One to Pick?

If-Else or Switch-Case: Which One to Pick?

Sumudu Siriwardana on November 10, 2021

This article was originally published on Dasha In case you are wondering, Dasha is a conversational-AI-as-a-service platform that lets you embed ...
Collapse
 
jonrandy profile image
Jon Randy 🎖️ • Edited

You can also use switch like this:

switch(true) {
  case x==1:
    // code block
    break;
  case y==3:
    // code block
    break;
  case z / 5 >= 3:
    // code block
    break;
  default:
    // code block
} 
Enter fullscreen mode Exit fullscreen mode
Collapse
 
sumusiriwardana profile image
Sumudu Siriwardana

Yes, thank you for mentioning that. But I've heard that having "true" is not the best practice of writing it. But I definitely have to do more research on this and understand why.

Collapse
 
darkwiiplayer profile image
𒎏Wii 🏳️‍⚧️ • Edited

Because jump-tables go out the window when your cases aren't constants. Other languages (Looking at you, C) don't even allow this in the first place.

If you ask me, this is not a good reason to avoid using this feature; but one should be aware that it won't be optimised the way you could with constant expressions*.

* Although, a really smart JIT-Compiler might figure out that an expression is constant for a specific closure (or trace, if it's a tracing JIT) and optimise it into a jump table. Don't think any JIT would bother with such a specific optimisation, but it is an option.

Thread Thread
 
pinotattari profile image
Riccardo Bernardini • Edited

A good reason to avoid this construct is readability: the typical "switch" construction is turned upside-down with a constant as "controlling value" and non-constant cases. ...and this flip gets you... nothing?

It is interesting as study case, as "look what you can do" but I cannot see a reason (read: a real advantage) to use it in a real case and the disorientation that causes to the reader is a big disadvantage.

Collapse
 
jonrandy profile image
Jon Randy 🎖️ • Edited

Don't see why not. It can make some convoluted blocks of ifs easier to read if you ask me. Nothing odd going on - switch just compares the value of one expression with the values of the expressions listed as the cases. We can match any expressions that are true.

It's probably not considered 'best' practice as it doesn't adhere to the irrational dogma of the high priests of 'clean' code

Thread Thread
 
murkrage profile image
Mike Ekkel

There's literally no need for the last sentence of your comment.

As to why it's considered not a best practice: while you could definitely use a screwdriver as a hammer, that's not the intended use. It's an incredibly smart way of using the switch statement but it's not the way it's intended to be used and as such is harder for people to understand.

Collapse
 
darkwiiplayer profile image
𒎏Wii 🏳️‍⚧️

In the if-else case, we do not create a jump table, and all cases are executed at runtime.

This is not necessarily true; compilers may still optimise if-statements into jump-tables if they're simple enough. Whether any compiler bothers doing this is another question, of course.


Also, another option is to build your own jump-tables. In JavaScript, these are called "objects" 😜

Collapse
 
peerreynders profile image
peerreynders • Edited

When in doubt — use functions.

const topResult = (next) => (grade) =>
  grade === 'A+' ? 'Nailed It! 🥳' : next(grade);

const midGrades = new Set(['A', 'B+', 'B']);
const midResult = (next) => (grade) =>
  midGrades.has(grade) ? 'Passed 💃' : next(grade);

const lowResult = (next) => (grade) =>
  grade === 'C' ? 'Barely Survived 😌' : next(grade);

const failResult = (_grade) => 'Failed 😢';

const studentFinalResult = topResult(midResult(lowResult(failResult)));

console.log(studentFinalResult('A+')); // "Nailed It! 🥳
Enter fullscreen mode Exit fullscreen mode

😁

MDN: Closures

Collapse
 
taniarascia profile image
Tania Rascia

This is uniquely terrible. It's so much less readable than either an if/else or a switch.

Collapse
 
peerreynders profile image
peerreynders

This is uniquely terrible.

Chain of Responsibility sends its regards.

Collapse
 
foxy4096 profile image
Frox

wait what is === and == and = in js
three equal to sign is very confusing

Collapse
 
jonrandy profile image
Jon Randy 🎖️

= is assignment
== is equality (no type checking)
=== is strict equality (type checking)

My explanation here is greatly simplified - the rules for equality when using == are quite complex

Collapse
 
pinotattari profile image
Riccardo Bernardini

the rules for equality when using == are quite complex

Alas, that is one of the worst sin of JavaScript. == is not even transitive, which is a basic property that you would expect from equality. It is not just an academic matter, some algorithms (e.g., sorting) make the implicit hypothesis that equality is transitive and they can break down if it is not. The reason why we do not observe many break downs is that in sorting procedures data are of the same type and this "feature" of JS == (but also PHP has the same problem) does not manifest itself.

Collapse
 
sumusiriwardana profile image
Sumudu Siriwardana

Jon has explained it very simply!

It might help you to get a basic idea of JS operator with this article
dev.to/sumusiriwardana/beginners-g...

Collapse
 
Sloan, the sloth mascot
Comment deleted
Collapse
 
pinotattari profile image
Riccardo Bernardini

I do not have the possibility of checking it, but if I remember correctly

"1.200" == "1.2"
Enter fullscreen mode Exit fullscreen mode

is true because since both sides "look" like floating point numbers, they are converted both to float before doing the comparison.

Collapse
 
pinotattari profile image
Riccardo Bernardini

A side note from a different language...

In Ada you can use switch .. case (actually it is case .. when like in Ruby) only with discrete types: integers and enumerations. The nice part of the case in Ada is that you are obligated to specify all the cases. It can seem like a burden, but it saved me from many bugs that would had happened because I forgot to update a case after adding a new item to an enumeration type.

Of course there is the "default" case (when other), but I try to avoid it since it "disables" the safety check that all the cases are specified.

What about when you do a case with an integer? You cannot, of course, specify all the integers... Well, in that case you can use the when other (it is legit, after all), but often is better to define a new integer type with explicit bounds.

Collapse
 
peerreynders profile image
peerreynders

TypeScript supports exhaustiveness checking on union types.

type Grade = 'A+' | 'A' | 'B+' | 'B' | 'C' | 'D' | 'F';

function studentFinalResult(grade: Grade): string {
  switch (grade) {
    case 'A+':
      return 'Nailed It! 🥳';
    case 'A':
    case 'B+':
    case 'B':
      return 'Passed 💃';
    case 'C':
      return 'Barely Survived 😌';
    case 'D':
    case 'F':
      return 'Failed 😢';
    default:
      const _exhaustiveCheck: never = grade; // "Type 'string' is not assignable to type 'never'".
      return _exhaustiveCheck;               // if one of the union type values is missing
  }
}

console.log(studentFinalResult('A+')); // "Nailed It! 🥳"
Enter fullscreen mode Exit fullscreen mode

playground

Collapse
 
taniarascia profile image
Tania Rascia

If you can turn an if/else into a switch, it's probably better as an object.

const NAILED_IT = "Nailed It! :partying_face:";
const PASSED = "Passed :dancer:";
const BARELY_SURVIVED = "Barely Survived :relieved:";
const FAILED = "Failed :cry:";

const gradeMap = {
  'A+': NAILED_IT,
  'A': PASSED,
  'B+': PASSED,
  'B': PASSED,
  'C': BARELY_SURVIVED,
  'D': FAILED,
  'F': FAILED
}

return gradeMap[grade]
Enter fullscreen mode Exit fullscreen mode
Collapse
 
aerodarius profile image
Dario Cruz

"maps" ofcourse, neither "if-else", nor "switch"