• onelineftw (unregistered)

    How about: m.values[min(3,Math.floor((d-1)/15000))]++

  • Debra (unregistered)

    m.values[d > 45000 ? 3 : d / 15000]++ anyone?

  • pbb (unregistered) in reply to Debra

    That's what ternaries were created for!

  • (nodebb)

    Seen it before. The perpertrator's excuse was along the lines of how switch's lookup tables are more efficient or something. Never mind that the conditions have to evaluated first.

    Makes me wonder now, actually: would this typically cause all of them to be evaluated, rather than evaluating as few as possible to find the first match?

  • bvs23bkv33 (unregistered)

    i think "could" code could run even in c

  • King (unregistered) in reply to Debra

    Will not work: if d < 0, d == 15000, d == 30000, d == 45000 or if d is a float, or ( I think) if d is a non-integer string.

  • unregistered (unregistered)

    This is actually quite useful for evaluating Radiobuttons:

    switch(true) { case Radiobutton1.Selected: ... case Radiobutton2.Selected: ... }

    Although doing it in languages that require an explicit break don't make it simpler than if/else.

  • Little Bobby Tables (unregistered)

    Apart from the lack of parameter checking, I can't really see the problem.

    a) The numbers are hardwired -- but then they'll also be hardwired when you're writing your if.

    b) It assumes d is an integer and non-negative

    Apart from that, it's obvious what it does, it's more-or-less clean, and it clearly works.

    Where's the WTF?

  • rosuav (unregistered) in reply to Little Bobby Tables

    This is the exact sort of code I routinely reject from my students. It's an abuse of switch and is much more clearly written as simple 'if' statements.

    (And yes, I routinely reject it because it routinely comes up.)

  • dpm (unregistered)

    I actually like your idea, especially if the tests are slightly modified so that "d" is always in the middle:

    m.values[0] +=                          d <= 15000;
    m.values[1] += 15000 < d && d <= 30000;
    m.values[2] += 30000 < d && d <= 45000;
    m.values[3] += 45000 < d;
    

    because it's quite intuitive at a glance to see exactly what gets incremented when. Of course the variable names are meaningless and the array indices should be named, but it's still easier to read than multiple "if"s.

  • (nodebb)

    Meh. switch(true) is an idiom that I've seen before; some strange people are fond of it. Not a style I like, but not a WTF.

  • (nodebb)

    A thing about

    switch/[code], at least in C/C++/C# is that the values are compared in order.  If a test matches, then the subsequent tests are not performed.  Therefore, the [code]switch
    conditions could be simplified.

    switch (true) {
    	case (d <= 15000):
    		m.values[0]++;
    		break;
    	case (d <= 30000):
    		m.values[1]++;
    		break;
    	case (d <= 45000):
    		m.values[2]++;
    		break;
    	default:
    		m.values[3]++;
    		break;
    }
    

    Addendum 2018-11-19 08:40: Oops. We need a Preview button to catch errors like this as well as a link to the markup definitions.

  • (nodebb)

    I used to love this construct when writing visual basic (select case true). It made perfect sense, and VB didn't require a break statement. I was initially tripped up on that when moving to other languages; you're selecting a case, you shouldn't need to break. Efficiency was the same, it read better than lengthy if else blocks, and it included an else case.

  • Wizard (unregistered)

    Ummm..... 15000, 30000, 45000 ???? Easily divisible to calculate which index you need to increment! No "Switch", No "If"...

    (yes it's true in this case you say but then whats wrong with calling a function passing in the number and it returns the index. Hide the implementation guys!)

  • NoLand (unregistered)

    For obscurity bonus:

    d <= 15000 && m.values[0]++; d > 15000 && d <= 30000 && m.values[1]++; d > 30000 && d <= 45000 && m.values[2]++; d > 45000 && m.values[3]++;

    (clicking 'submit' and hoping the best for formatting.)

  • John C. Flack (unregistered)

    The IF solution would be nested if/else statements. For four possible paths, this would be reasonable, but the more paths, the more I would want to flatten it into the switch. Too easy to mess up the nested ifs when a later modification needs to add some other paths.

    I will admit that there are languages that do "switch" for this sort of thing better than JS. And there are languages that have an "elseif" key word to do the nested if/elses more clearly.

  • Guest (unregistered) in reply to Nutster

    How is this better than:

    if (d <= 15000) m.values[0]++;
    else if (d <= 30000) m.values[1]++;
    else if (d <= 45000) m.values[2]++;
    else m.values[3]++:
    

    I struggle to see any cases where using the switch/case form over the if-else form saves you anything. Even in Javascript where every character counts, this is fewer characters once you include the "break;" line for each of these.

    (And yes - as Wizard points out it's pretty clear here that some variation on using d/15000 as the index into the array without a set of checks at all is the better choice.)

  • rstejskal (unregistered) in reply to Nutster

    In C/C++/C#, the expressions in case labels must be constants, so this sort of nonsense isn't possible to begin with.

  • Giulio (unregistered)

    Case is shorter than else if, but you don't need to repeat the lower bounds, if you use else ifs, because they'll be implied by the "else".

  • AJM (unregistered)

    Am I missing something? In the original the array value is incremented:

    m.values[x]++

    If d == 1001 and m.values[0] == 25, after the check m.values[0] == 26.

    In the revised the array value is added to d.

    If d == 1001 and m.values[0] == 25, after the check m.values[0] == 1026.

    Is this the same as what is intended in the original code or am I missing something?

  • Gnasher729 (unregistered)

    In Swift, this is actually quite similar to the recommended style - you do use the value to be switched on (and the value can be a tulle), but the cases can handle ranges.

  • Gnasher729 (unregistered) in reply to Gnasher729

    Bloody spelling checker: switch values can be tuples. Anyone knows what a tulles is?

  • Gnasher729 (unregistered) in reply to Gnasher729

    Bloody spelling checker: switch values can be tuples. Anyone knows what a tulles is?

  • Pedro (unregistered) in reply to NoLand

    Single liner: d <= 15000 && m.values[0]++ || d <= 30000 && m.values[1]++ || d <= 45000 && m.values[2]++ || m.values[3]++;

  • Pedro (unregistered) in reply to Gnasher729

    Tulle (noun): a soft, fine silk, cotton, or nylon material like net, used for making veils and dresses.

  • Perri Nelson (unregistered) in reply to Gnasher729

    Tulle: A lightweight, very fine netting. Not often used for calculating primes.

  • (nodebb)

    I've seen plenty of people advocate this style in Stack Overflow answers for both JavaScript and PHP. I personally think it's gross.

    But what do I know? I also feel that many complex uses of array.reduce() to construct objects from arrays are inappropriate.

  • grasshoppa (unregistered)

    Call me crazy, but I don't see the problem. I prefer the switch syntax to the ifelse syntax, I think it's more obvious what's going on ( plus, as has been mentioned, the switch syntax could be simplified as it stops evaluating when it finds a hit ), plus as you add more conditions ( and this looks like a section which would end up having more conditions eventually ) it keeps the verbosity and the simplicity in place ( where as the ifelse could quickly become a nightmare ).

  • (nodebb) in reply to AJM

    Apparently the boolean expression is evaluated as an integer in this situation, so true becomes 1 and false becomes 0. Try it in the console.

  • Alex (unregistered)

    That you can write stuff like this without a syntax error is one of the reasons I don't do JavaScript.

  • Kevin (unregistered) in reply to Nutster

    m.values[Math.max(((int)d / 15000) - 1, 3)]++;

  • ZPedro (unregistered)

    You are but children. Watch:

    m.values[(d>15000) + (d>30000) + (d>45000)]++;
  • Matías Moreno (google)

    m.values[Math.max(0,Math.min(3,((d-1)/15000)|0))]++

  • tlhonmey (unregistered)

    Obviously they cleaned this up from a previous incarnation where it was switching on the value of d and had a case for every possibility in each of the ranges.

    Well, probably had a case for every possibility. Usually that kind of thing ends up with some missing bits here and there that yield strange results but it can't be fixed because whoever's looking at the output would panic over the discrepancy...

  • smf (unregistered)

    The enterprisey way of doing it

    m.values[d <= 15000 ? 0 : d <= 30000 ? 1 : d <= 45000 ? 2 : 3]++;

  • John (unregistered)

    https://en.wikipedia.org/wiki/The_Elements_of_Programming_Style "5. Write clearly -- don't sacrifice clarity for efficiency."

  • Merus (unregistered)

    This is a pretty standard idiom in Ruby, as well, which might well explain its presence here if the dashboard is on Rails. Case in Ruby can take no object, which makes case execute the first block with a statement that evaluates to true. Of course, Ruby case doesn't have fallthrough and the explicit ranges are bad in any language.

  • (nodebb)

    This is actually a common usage pattern in (surprise...) Cobol.

    Languages with C-like syntax allow one to omit the braces if one has a single statement in either of the branches. When one puts an "if" in the "else" part, one is actually going one nesting level deeper using this single "if" statement. If one has three "else if" following the first "if", then the last one is three levels deep. One is (ab)using this single-statement loophole to avoid the technically correct deeper indentation on the else parts.

    Cobol (and of course a few others) needs an END-IF to end an IF(*). When one needs ELSE IF parts, they actually have to have deeper and deeper indentations, or else the series of END-IF in the end, all starting on the same column, will look weird. Thus the switch-case equivalent of EVALUATE is used with TRUE.

    (*) In the relatively "modern" versions of Cobol. The older Cobol IF syntax ends with a period ("."), but it ends all inner nested things too. Those issues, however, belong to another website (which should be) called thedailycobolwtf dot com (when it is born).

  • Anon (unregistered)

    Worse? Have you considered the goto statement?

  • I'm not a robot (unregistered) in reply to DrOptableUser
    One is (ab)using this single-statement loophole to avoid the technically correct deeper indentation on the else parts.
    In C-like languages any indentation scheme is "technically correct". The indentation serves purely to make the code easier to read for people, and the
        if (...) {
            ...
        } else if (...) {
            ...
        }
    style fulfils that goal better than adding extra indentation for the second if.
  • (nodebb) in reply to rstejskal

    You are right, constants only. I have been playing in VBA/VB.Net too long. I need to get back to programming in C++ again.

  • (nodebb)

    Yeah, I would have written this as a if-else if-else series like that, but with the assignment clauses on new lines, rather than a funcky switch.

  • (nodebb)

    Really unreadable version:

    m.values[(d>15e3)+(d>3e4)+(d>45e3)]++;
    

    Can you beat 38 bytes?

  • Future (unregistered)

    The real WTF is, as usual, Javascript. Why is there a "break" for every switch case? How often do you need the fall through compared to how often you are writing break, effectively making the entire switch construction too unwieldy to use?

  • (nodebb) in reply to urkerab

    Hmmm, in a vectorized language, you might get away with

    m.values[ sum(d > 1.5e3*(1:3))]++

    Which at least looks cool, if not a code golf winner

  • WTFGuy (unregistered)

    Going way back in my increasingly flaky memory banks ...

    That style was also perfectly cromulent in DBase/FoxPro that had a switch construct (using the keyword "case" IIRC) but lacked an else if construct.

    Otherwise I agree it's a mild code smell.

  • Your Name. (unregistered)

    ++m.values[(d>15000) + (d > 30000) + (d > 45000)];

    Done.

  • Daniel (unregistered)

    It's clever, maybe a bit obscure for JS. It resembles pattern matching blocks in ML, Scala or Haskell. Pretty obscure though for JS.

  • fintux (unregistered)

    In case somebody comes to read the comments in 2020 or later... This looks like output from the CoffeeScript transpiler. For more details, see https://stackoverflow.com/questions/30493275/theoretical-coffeescript-switch-statement-conundrum. As to why this is generated by CoffeeScript instead of an if-else if-else is beyond me, though.

Leave a comment on “A Clever Switch”

Log In or post as a guest

Replying to comment #501218:

« Return to Article