Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Expression inside switch case statement

I'm trying to create a switch statement but I can't seem to be able to use an expression that gets evaluated (rather than a set string/integer). I can easily do this with if statements but case should hopefully be faster.

I'm trying the following

function reward(amount) {     var $reward = $("#reward");     switch (amount) {         case (amount >= 7500 && amount < 10000):             $reward.text("Play Station 3");             break;         case (amount >= 10000 && amount < 15000):             $reward.text("XBOX 360");             break;         case (amount >= 15000):             $reward.text("iMac");             break;         default:             $reward.text("No reward");             break;     } } 

Am i missing something obvious or is this not possible? Google hasn't been friendly in this case.

Any help/pointers appreciated

M

like image 328
Marko Avatar asked Aug 12 '10 00:08

Marko


People also ask

Can we have an expression inside the switch () statement?

The expression in the switch can be a variable or an expression - but it must be an integer or a character. You can have any number of cases however there should not be any duplicates. Switch statements can also be nested within each other.

What is expression in switch?

The result of a switch expression is the value of the expression of the first switch expression arm whose pattern matches the input expression and whose case guard, if present, evaluates to true . The switch expression arms are evaluated in text order.

Can we use expression in switch-case in JS?

The switch statement evaluates an expression. The value of the expression is then compared with the values of each case in the structure. If there is a match, the associated block of code is executed. The switch statement is often used together with a break or a default keyword (or both).

Which expression is not allowed in switch-case?

The value of the expressions in a switch-case statement must be an ordinal type i.e. integer, char, short, long, etc. Float and double are not allowed.


2 Answers

amount is a number, but the expressions in the case clauses only evaluate to booleans; the values will never match.

You could always do

switch (true) {   case (amount >= 7500 && amount < 10000):     // Code     break;   case (amount >= 10000 && amount < 15000):     // Code     break;   // etc. } 

It works because the value being matched is now the boolean true, so the code under the first case clause with an expression that evaluates to true will be executed.

It’s kinda “tricky”, I guess, but I see nothing wrong with using it. A simple ifelse statement would probably be more concise, and you’d not have to worry about accidental fall-through. But there it is anyway.

like image 191
MooGoo Avatar answered Oct 16 '22 03:10

MooGoo


@MooGoo's switch (true) will give you a Weird condition error in jsLint, so let's get a little more creative in case that's an issue, and, I think, increase readability a touch.

So we're not evaluating if each case is true or false; we're comparing if that case's value is equal to our switch term. So let's take advantage of that by throwing a shorthand if into our case statement and return our original switch term if the condition's true.

I'm also including a sort of real world example, where you want to have two "defaults" -- one if your term is outside of your "important" range in the positive direction, and another in case you're in the negative direction.

Key phrase: case (x > 0 ? x : null):

"If my term, x, is greater than zero, return x so that x === x and I take the case branch."

http://jsfiddle.net/rufwork/upGH6/1/

/*global document*/ /*jslint evil:true*/ var x = 10;  switch (x) {     case (x > 0 ? x : null):         document.write('ha ha ha!  I fooled switch AND jsLint!  Muhahahahaha!');         break;     case 0:         document.write('zero is nothing.');         break;     case -1:         document.write('low');         break;     case -2:         document.write('lower');         break;     case -3:          document.write('lowest I care about');         break;     default: // anything lower than -3.         document.write('TOO LOW!!!! (unless you cheated and didn\'t use an int)'); } document.write('<br>done.'); 

Quick reply to @Sv443:

Do notice that the default: switch says, "unless you cheated and didn't use an int" and that short circuiting requires x === x when you return x.

But your point is a useful reminder that NaN is the only case where short circuiting can't apply.

That is, x must == x to short circuit in switch and, as MDN tells us, "NaN, and only NaN, will compare unequal to itself" (double or triple =).

That also means that switching on a NaN value (and only a NaN value) will always hit default in ANY switch because you can't match its value.

Here's the full quote from MDN:

NaN compares unequal (via ==, !=, ===, and !==) to any other value -- including to another NaN value. Use Number.isNaN() or isNaN() to most clearly determine whether a value is NaN. Or perform a self-comparison: NaN, and only NaN, will compare unequal to itself.

You could change the default logic to check what you have:

isNaN(x) ? document.write ('nan') : document.write('TOO LOW!!!! ...)');

Or you even could go full hipster like MDN suggests (but please don't ;^D):

x !== x ? document.write ('nan') : document.write('TOO LOW!!!! ...)');

like image 41
ruffin Avatar answered Oct 16 '22 01:10

ruffin