[update 2014 Nov 04]
Please read this post in conjunction with: https://dbj.org/dbj-cond/
[end of update]
The other day on jQuery forum, I spotted a code like this one:
(first published 06JUN09)
1 2 3 4 5 6 7 8 9 |
jQuery('a').each(function(){ switch(x) { case 1: $(this).css({ color:'blue'}); break ; case 2: $(this).css({ color:'red'}); break ; default : $(this).css({ color:'green'}); } }); |
Unfortunately, for some, this is “too many keystrokes” … And peculiarly (then very young and rushed) Mr B. Eich forgot to make a result of the switch available, so this was not possible in JavaScript:
1 2 3 4 5 6 7 8 9 10 11 |
// var color = switch(x) { case 1: 'blue' ; break ; case 2: 'red' ; break ; default : 'green' ; }; // above is or was an unexpected token error // 2018JUL17 : "Unexpected token switch" // in Chrome and Opera, "Syntax Error" in Edge // |
As far as JavaScript parsers (some of them) are concerned “switch” above is an “unexpected token” error.
Update 2017-10-24
For my browser this (of course) is no longer the case and switch behaves as it should do. My browser user agent string is this:
1 2 3 4 5 6 7 8 |
navigator.userAgent "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.86 Safari/537.36" |
Back to distant past. Added peculiarity is that the following code parses OK,
1 2 3 4 5 6 |
var x = 2 ; switch(x) { case 1: 'blue' ; break ; case 2: 'red' ; break ; default : 'green' ; }; |
The latest statement is the switch and it returns “red”, indeed. And yes You are free to try and “give it” to the return statement. That might not work too.
1 2 3 4 5 6 7 8 9 10 11 |
var x = 2 ; function swtch(x) { // this might be an // "unexpected token error" return switch(x) { case 1: 'blue' ; break ; case 2: 'red'; break ; default : 'green' ; }; } // |
One roundabout way is to get to the return value of the switch, with eval(), like this :
1 2 3 4 5 6 7 8 9 10 11 12 |
var color = eval( 'switch(x){' + 'case 1: "blue"; break;' +' case 2: "red"; break;' +' default: "green" } ' ) ; // // this works // but is almost useless // as a solution // |
The issue is that switch; statement, after all, returns the value, but it is not a legal ‘rvalue’ in some JavaScript engines. At the moment. The eval() trick is not very useful and looks somewhat dodgy. So some developers have concluded they “must help” everyone with the function similar to this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
// //return the value if x matches the case //case and value must be in pairs //the last argument if given is the default value // //cond( input, // case1, value1, // case2, value2, // ..... , // otherwise_value ) // //example : // cond( x, 1, "blue", 2, "red", /*otherwise*/ "green" ) ; // |
It has to be said that this is directly inspired by the LISP (COND …) construct. And, by now the excitement in the forum is high indeed because one can safely write this:
1 2 3 4 5 6 |
$(this).css({ color: cond( x, 1,"blue", 2,"red", /*otherwise*/ "green" } ) ; |
Also much cleaner and shorter than the very first snippet in this post. Quick and dirty, and very workable, cond function is this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
//last argument is default value function cond( v ) { var j = 1 ; for ( ; j < arguments.length; j+=2 ) { if ( cond.cond(v,arguments[j]) ) return arguments[j+1]; } return (!arguments[j-2]) ? undefined : arguments[j-2] ; } // allow users to change the condition // operator used to match the value given // default condition is 'deep equality', // aka 'exact match' cond.cond= function (a,b) { return (a) === (b) ; } |
Example usage:
1 2 3 4 |
cond( 1, 2, "apples", 1, "pears", "none" ) /* returns: "pears" */ |
For some, this is “Awesome”, while for others this is “obfuscation”. Personally, I like it but I vote for ECMA to simply allow assignment with the ‘switch’ statement to be a legal “rvalue”. That is: make the return value of the switch statement available for assignment:
1 2 3 4 5 6 7 8 |
//My ECMA proposal var color = switch(x) { case 1: "blue"; break; case 2: "red"; break; default: "green" } ; //make this possible //by making switch act as an rvalue too |
Although. (It has to be said) I rather like cond() and I think it delivers much more readable robust code. Thus I have added this for everyone to use, to the NPM in the form of dbj.cond() .
Enjoy
–DBJ
Update 2010.Jan.10
Ben Alman made this idea into a useful jQuery plugin, here: http://benalman.com/projects/jquery-cond-plugin/
8 thoughts on “My ECMA Proposal : make switch useful”
Update
Interesting (probably for some readers) is that this cond() function could replace each and every switch() and of course if … then … else … if … else …, “cascades” , which obviously will lead to a more compact code. But not necessarily a faster one.
Although I have not tought yet about optimising the cond() function …
If you’re after an evaluating switch, how about this? https://gist.github.com/3975291
@bleroy Thanks for reading. I am not after “evaluating switch” , I am rather after ECMA comitee making standard switch an “rvalue”. But Your swtch() is clever nevertheless.
I understand, and I agree that extending the EcmaScript switch to support this would be ideal. Can’t see a downside to it really. Looks like a simple oversight, and there are no back-compat issues that I can think of.
I just posted an alternative to your cond function http://js-bits.blogspot.com/2014/11/using-objects-for-switch-statements.html
@Juan Mendes: Thanks for reading and commenting.
There is also a sequel to this “story” here: https://dbj.org/blog/2013/07/10/dbj-cond/
With a link to the GITHUB project.
In any case I approve of you making an effort. But please do not forget one simple truth:
After reading your article I do still prefer a first idea and solution. Mine that is.
I think it is simpler and easier to type and dbj.cond() also has no problems with using functions as parameters. Which are actually necessary vs LISP, as explained here:
https://dbj.org/2014/09/07/javascript-with-proper-if/
I know, I know… “JavaScript is LISP with C syntax” Since I prefer C/JavaScript syntax, I decided to offer the same behavior with C/JavaScript Syntax for those of use that prefer JavaScript :) Now that I’ve seen your version of cond that accepts functions, I think they are pretty much equivalent. Here’s another article that doesn’t create a cond function, but talks about using objects for switches: http://toddmotto.com/deprecating-the-switch-statement-for-object-literals/
@Juan .. I do believe classes, polymorphizm and inheritance are not meant to be emulated in JavaScript. So this is first line we draw :)
Second toddmotto article “I do not dig” … I see nothing “nice and easy” in his proposal?
AFAIK, Bertrand Le Roy has proposed simple and less obfuscated, object literals based solution already , here: https://gist.github.com/anonymous/3975291
Thanks for your comments anyway :)