How not to use a switch statement



  • Just came across this JavaScript:

    switch (true) {
    	case (ItemID === eItems.Item1.Id):
    		// do stuff
    		break;
    	case (ItemID === eItems.Item2.Id):
    		// do stuff
    		break;
    	case (ItemID === eItems.Item3.Id):
    		// do stuff
    		break;
    	case (ItemID === eItems.Item4.Id || ItemID === eItems.Item5.Id || ItemID === eItems.Item1.Id):
    		// do stuff
    		break;
    }
    

  • BINNED

    It looks like something someone whose first language was COBOL would write.



  • Yeah... that's clearly wrong! You're supposed to do this:

    switch (true) {
    	case (ItemID === eItems.Item1.Id):
    		// do stuff
    		break;
    	case (ItemID === eItems.Item2.Id):
    		// do stuff
    		break;
    	case (ItemID === eItems.Item3.Id):
    		// do stuff
    		break;
    	case (ItemID === eItems.Item4.Id):
    	case (ItemID === eItems.Item5.Id):
    	case (ItemID === eItems.Item1.Id):
    		// do stuff
    		break;
    }
    


  • Exactly! I just found that style lower down in the code.



  • Even PHP programmers wouldn't generally make that mistake.



  • The best parts are the first and last Items.



  • @riking said:

    Yeah... that's clearly wrong! You're supposed to do this:

    No, no, no! This is how you do it:

    switch (true) {
    	case (ItemID === eItems.Item1.Id):
    		// do stuff A
    		break;
    	case (ItemID === eItems.Item2.Id):
    		// do stuff B
    		break;
    	case (ItemID === eItems.Item3.Id):
    		// do stuff C
    		break;
    	case (ItemID === eItems.Item4.Id):
    		// do stuff D
    		break;
    	case (ItemID === eItems.Item5.Id):
    		// do stuff D
    		break;
    	case (ItemID === eItems.Item1.Id):
    		// do stuff D
    		break;
    }
    


  • Bonus points if // do stuff D is copy-pasted block, and not a function call.



  • The // do stuff statements are like this:

    orderInstance.Group1Modified = true;
    


  • Wow, I never would have thought to abuse a switch like that.

    At least it didn't start with switch (false) ...



  • Interesting pattern. Never seen it before. Hope I never do again.

    +1 for the WTF find.


  • 🚽 Regular

    What exactly is supposed to happen when ItemID === eItems.Item1.Id?



  • I'm 99% sure that this is the full code:

    switch (true) {
    	case (ItemID === eItems.Item1.Id):
    		return eItems.Item1.Id;
    		break;
    	case (ItemID === eItems.Item2.Id):
    		return eItems.Item2.Id;
    		break;
    	case (ItemID === eItems.Item3.Id):
    		return eItems.Item3.Id;
    		break;
    	case (ItemID === eItems.Item4.Id || ItemID === eItems.Item5.Id || ItemID === eItems.Item1.Id):
    		return ItemID;
    		break;
    }
    


  • This is the topvoted paradigm in this stack overflow question.

    Comments include "Very intriguing and creative solution!", "I'd mark this as the answer... awesome solution!"


  • BINNED

    @fowkc said:

    This is the topvoted paradigm in this stack overflow question.

    Comments include "Very intriguing and creative solution!", "I'd mark this as the answer... awesome solution!"

    Well, that's about it for the leftovers of my faith in SO answers...



  • Well, that's about it for the leftovers of my faith in javascript...



  • I had a question a couple of days back where I was working with something originally written using jQuery to do some not-especially complex DOM manipulations and I specifically asked for 'without jQuery' on the Googles. Heck, I even did -jQuery and I still got back 'with jQuery' answers.

    More worryingly were the number of people who'd specifically asked for 'without jQuery' that got 'just use jQuery'. Fucking SO.


  • BINNED

    @Medinoc said:

    Well, that's about it for the leftovers of my faith in javascript...

    I'm pretty sure it would work in C.

    onyx@jarvis:~/Desktop$ cat test.c 
    #include <stdio.h>
    #define true 1
    
    int main(void)
    {
        switch(true) {
            case(1 == 2):
                printf("Nope!\n");
                break;
            case(2 == 2):
                printf("Yup!\n");
                break;
            default:
                printf("FILE_NOT_FOUND\n");
        }
    
        return 0;
    }
    onyx@jarvis:~/Desktop$ gcc test.c -o test
    onyx@jarvis:~/Desktop$ ./test 
    Yup!
    onyx@jarvis:~/Desktop$ 
    
    

  • 🚽 Regular

    @Arantor said:

    More worryingly were the number of people who'd specifically asked for 'without jQuery' that got 'just use jQuery'.
    Any "use jQuery's source code as a reference of what to do"?
    @Arantor said:
    Fucking SO.
    Those are the best.



  • Actually, no, there weren't any suggestions like that. We were talking DOM traversal, rewriting crap like .closest() and so on. In the end I gave up trying to reuse the original code and just tweaked the HTML I was working with to just be simpler to navigate in the first place, i.e. what I should have done the first time around even when I did have jQuery available to me.



  • This can be vastly improved:

    switch (false) {
    	case (ItemID === eItems.Item1.Id ? false:true):
    		// do stuff
    		break;
    	case (ItemID === eItems.Item2.Id ? false:true):
    		// do stuff
    		break;
    	case (ItemID === eItems.Item3.Id ? false:true):
    		// do stuff
    		break;
    	case false: // "default"
    		// do stuff
    }
    

    or even using magic numbers for additional (ahem) clarity:

    switch (47) {
    	case (ItemID === eItems.Item1.Id ? 47:-1):
    		// do stuff
    		break;
    	case (ItemID === eItems.Item2.Id ? 47:-2):
    		// do stuff
    		break;
    	case (ItemID === eItems.Item3.Id ? 47:-3):
    		// do stuff
    		break;
    	case 47: // "default"
    		// do stuff
    }


  • @Keith said:

    I'm 99% sure that this is the full code:

    switch (true) {
    	case (ItemID === eItems.Item1.Id):
    		return eItems.Item1.Id;
    		break;
    	case (ItemID === eItems.Item2.Id):
    		return eItems.Item2.Id;
    		break;
    	case (ItemID === eItems.Item3.Id):
    		return eItems.Item3.Id;
    		break;
    	case (ItemID === eItems.Item4.Id || ItemID === eItems.Item5.Id || ItemID === eItems.Item1.Id):
    		return ItemID;
    		break;
    }
    ```</blockquote>
    
    No return statement, see post 9:
    http://what.thedailywtf.com/t/how-not-to-use-a-switch-statement/1590/9


  • @Arantor said:

    I had a question a couple of days back where I was working with something originally written using jQuery to do some not-especially complex DOM manipulations and I specifically asked for 'without jQuery' on the Googles. Heck, I even did -jQuery and I still got back 'with jQuery' answers.

    More worryingly were the number of people who'd specifically asked for 'without jQuery' that got 'just use jQuery'. Fucking SO.

    I would say that the term "DOM manipulation" usually gets me to use jQuery.



  • @PJH, can you change edit time limits per category? Having a super long time limit on the CodeSOD category would be awesome, so that I could update the original code if I decide that it needs clarification (in this instance, showing what "do stuff" is).


    Filed under: delerium
    It's easier for everyone to read topics that have fewer in-depth replies versus lots of small, individual replies.



  • I refuse to add jQuery for a dozen lines of code, when I can rewrite it to a dozen different lines of code without jQuery.



  • @Arantor said:

    I refuse to add jQuery for a dozen lines of code, when I can rewrite it to a dozen different lines of code without jQuery.

    Yeah, if you can write maintainable non-jQuery code, then by all means, do.



  • Well, here's the most complex DOM manipulation I was talking about. I'm sure people could pull WTFs apart out of it but frankly it's something I'm doing for other people as a favour, and I don't like JS much.

    The context is showing a dialogue for anti-spam Q&A, where each question can have multiple answers. It's grabbing the click off an a href, traversing up the container a couple of levels (for the container that holds all the inputs relating to the current question), and looks for the first thing that's an input. It's not a perfect piece of code, granted, nor is it a perfect replacement for the original JS but since I know that I'm the only person maintaining it and have no plans to maintain the JS any more than necessary, it's not entirely terrible.

    
    		function addAnswer(obj)
    		{
    			var childnodes = obj.parentNode.parentNode.childNodes;
    			var attr = childnodes[0].nodeType == Node.ELEMENT_NODE ? childnodes[0].getAttribute("name") : childnodes[1].getAttribute("name");
    			obj.parentNode.insertAdjacentHTML(\'beforebegin\', \'<input type="text" name="\' + attr + \'" value="" size="50" class="input_text verification_answer">\');
    			return false;
    		}
    

    Specifically, it's a backported function from SMF 2.1 to SMF 2.0 as an add-on where 2.1 ships bundled with jQuery and 2.0 doesn't.



  • @Arantor said:

    var childnodes = obj.parentNode.parentNode.childNodes;

    I usually wrap that in a recursive function that seeks a unique (or at least important) identifier.



  • @antiquarian said:

    It looks like something someone whose first language was COBOL would write.

    It reminds me most of Lisp's cond.



  • Eh, for something that is in every respect already obsolete and temporary, I'm not worried by it.



  • #define true false
    


  • You want the evil ideas thread --> that way


  • BINNED

    @chubertdev said:

    ```c
    #define true false

    
    I saw this somewhere, accompanied by `// Happy debugging, bitches!`
    
    Not sure if fake. But plausible.
    
    ---
    *<small>Filed under: [CBA to fix Discurse's fuckups, deal with it](#)</small>*

  • :belt_onion:

    @noland said:

    [code]
    switch (47) {
    case (ItemID === eItems.Item1.Id ? 47:-1):
    // do stuff
    break;
    case (ItemID === eItems.Item2.Id ? 47:-2):
    // do stuff
    break;
    case (ItemID === eItems.Item3.Id ? 47:-3):
    // do stuff
    break;
    case 47: // "default"
    // do stuff
    }
    [/code]

    You're getting there, but still not quite abusive enough...
    [code]
    var doStuff;
    switch (47) {
    case (ItemID === eItems.Item1.Id ? 47:-1):
    doStuff = function(){ //do the stuff };
    break;
    case (ItemID === eItems.Item2.Id ? 47:-2):
    doStuff = function(){ //do the stuff };
    break;
    case (ItemID === eItems.Item3.Id ? 47:-3):
    doStuff = function(){ //do the stuff };
    break;
    case 47: // "default"
    doStuff = function(){ //do the stuff };
    break;
    }
    doStuff();
    [/code]



  • @fowkc said:

    This is the topvoted paradigm in this stack overflow question.

    Comments include "Very intriguing and creative solution!", "I'd mark this as the answer... awesome solution!"

    I assumed those were sarcasm until I saw how many upvotes that answer had.



  • All praise the power of community crowdsourced knowled... wut.


  • :belt_onion:

    rofl... checkmarked as correct answer with a -3, because he's technically wrong - it can be done, but dear $DEITY should it not ever be.


  • This is the worst example of SO yet, I think. Need to bookmark this for future reference.



  • @Arantor said:

    This is the worst example of SO yet, I think. Need to bookmark this for future reference.

    Worse than the jQuery for addition one?



  • It's worse than this one


  • :belt_onion:

    That one's just a stupid question, the answers appear to be fine.



  • I was thinking more of this.



  • I couldn't find it quickly is all. I don't have much bookmarked on SO.


  • :belt_onion:

    +107 I see you're trying to determine when to use jQuery by analyzing the problem at hand and applying logic and reason to make an informed decision about its possible implementation. You should totally drop that and try jQuery.
    They see me trollin :trollface: they hatin :trollface: Rickrolling, they tryin to catch me postin nerdy :trollface:


  • Now, there we go:

    switch (42) {
    	case (function() {
    		return (ItemID === eItems.Item1.Id)?
    	    	    	(function() { /*do stuff*/ })()
    	    	    	&& 42:-1;
    		})(): break;
    	case (function() {
    		return (ItemID === eItems.Item2.Id)?
    	    	    	(function() { /*do stuff*/ })()
    	    	    	&& 42:-2;
    		})(): break;
    	/*...*/
    	case (42 && (function() { /* "default" */ })()): break;
    }
    

    Functional is the answer to life the universe and everything ...



  • Correction, should actually be:

    (function(answerToEverything) {
      var nope = ~answerToEverything;
      switch (answerToEverything) {
    	case (function(a, b) {
    		return (a === b)?
    	    	    	(function() { /*do stuff*/ })()
    	    	    	&& answerToEverything : nope;
    		})(ItemID, eItems.Item1.Id): break;
    	case (function(a, b) {
    		return (a === b)?
    	    	    	(function() { /*do stuff*/ })()
    	    	    	&& answerToEverything : nope;
    		})(ItemID, eItems.Item2.Id): break;
    	/*...*/
    	case (answerToEverything && (function() { /* "default" */ })()): break;
      }
    })(42);
    

    There's always another layer of functional, in case you would want it to be really live, universal and everythingy ...



  • @Onyx said:

    I'm pretty sure it would work in C.

    Try it with comparison to actual variables, e.g. "argv[1] == 5", then say if it is working.



  • If argv[1] == 5 is true, I'd be worried.



  • @noland said:

    Now, there we go:

    switch (42) {
    	case (function() {</blockquote>
    

    Clearly you are a lambdaUser, or just lUser for short.



  • You're all λusers!


Log in to reply