Arc Forumnew | comments | leaders | submitlogin
1 point by akkartik 5115 days ago | link | parent

"C style languages (including JavaScript) make `switch` so awful that you end up using if/else chains. A missed opportunity, to be sure. Arc does a better job, which is good."

I don't follow that at all.



1 point by Pauan 5114 days ago | link

In languages derived from C, including JavaScript, they use `switch` rather than `case`, like so:

  ; Arc

  (case x
    "foo" ...
    "bar" ...)


  // JavaScript

  switch (x) {
  case "foo":
      ...
      break;
  case "bar":
      ...
      break;
  }
As you can see, switch blocks are atrocious, especially because they require a break; statement or they'll fallthrough. So instead of using switch, some developers prefer if/else chains:

  if (x === "foo") {
      ...
  } else if (x === "bar") {
      ...
  }
Which, as you can see, are less verbose. Arc gets it right, JavaScript doesn't.

-----

2 points by thaddeus 5114 days ago | link

I'm going to argue that you're comparing apples to oranges to pears.

Arc and Javascript case functions are not expected to do the same thing. JS does not allow expressions for input arguments while Arc can. And that break; statement is a feature that some would say Arc lacks. ie, what if you want your case statement to fall through? - now Javascript is golden and one could say Arc is lacking.

I also don't believe developers, generally speaking, prefer if/else chains over switch/case statements as they are different tools intended for different purposes.

They both are not perfect, both are missing features that the other could benefit from.

I think Clojure got it right having it all: case + cond + condp.

-----

1 point by Pauan 5114 days ago | link

Not true... JavaScript allows arbitrary expressions in switch statements, so it does behave like Arc's `case`, only it's much more verbose:

  switch (true) {
  case 5 > 1:
      console.log("5 > 1");
      break;
  }
---

On the contrary, switch should not have a break statement! It should have a fallthru; or continue; statement. Why make the common case difficult? This should be uncontroversial... it's been well established that switch's design is poor, and they should have made it explicit fallthru (like with a continue statement) rather than implicit.

As for Arc "lacking" fallthru... can't you implement that with continuations? That would be the equivalent of explicit fallthru.

---

My point was that switch statements are so atrocious that even in the situations that they were intended for, some developers still prefer if/else chains because they're shorter and more readable.

-----

1 point by waterhouse 5114 days ago | link

> Why make the common case difficult?

I think that's because the above semantics correspond more directly to assembly language, which I imagine was done because "switch" was defined back when that was either important or just not seen to be bad. (Perhaps I'm just making that up, though.) Here's how a switch statement would look in x64 assembly:

  switch:
        ;put desired thing in rax, let's say
  case_1:
        cmp rax, val_1
        jne case_2      ;jump if not equal
        <case 1 code>
  case_2:
        cmp rax, val_2
        jne case_3
        <case 2 code>
  case_3:
        cmp rax, val_2
        jne done
        <case 3 code>
  done:
        <whatever>
By default, the machine will just plow through the remaining cases. If you want it to break out after one case, you have to tell it to do so:

  switch:
        ;put desired thing in rax, let's say
  case_1:
        cmp rax, val_1
        jne case_2      ;jump if not equal
        <case 1 code>
        jmp done        ;jump.
  case_2:
        cmp rax, val_2
        jne case_3
        <case 2 code>
        jmp done
  case_3:
        cmp rax, val_2
        jne done
        <case 3 code>
  done:
        <whatever>
Assembly language is kind of awesome, by the way. And so is the Miller-Rabin primality test. Some disorganized code: http://pastebin.com/raw.php?i=wRyQ2NAx

-----

1 point by Pauan 5114 days ago | link

Fine. That's great and all for C, but I dislike how Java copied C word-for-word, and then JavaScript copied Java. It would have been nice if they had said, "hm... using continue rather than break would make a lot more sense."

It's not a huge deal, and developers can simply avoid switch if they don't like it. My point was merely that "JavaScript's switch sucks, Arc's (case) is awesome."

-----

1 point by thaddeus 5114 days ago | link

a reply for one layer down:

> JavaScript allows arbitrary expressions in switch statements

That's right... looks like it was the test data I was thinking of, which isn't entirely relevant, given you can accomplish the same thing in the end.

> Why make the common case difficult?

A fall-through could be nicer than many breaks. Trying to think of all the scenarios required to make this usable, i.e., do you need a break to get out of a fall-through? Maybe that's why they just went with break. either way, it's a good idea.

-----

1 point by Pauan 5114 days ago | link

The current behavior for switch is simple: it will continue until it finds a break statement. Thus:

  switch (true) {
  case true:
      console.log(1);
  case true:
      console.log(2);
  case true:
      console.log(3);
      break;
  case true:
      console.log(4);
  }
...which outputs 1, 2, and 3. If you wanted to have the same behavior using the continue statement, you would use this:

  switch (true) {
  case true:
      console.log(1);
      continue;
  case true:
      console.log(2);
      continue;
  case true:
      console.log(3);
  case true:
      console.log(4);
  }
As far as I know, this would have exactly the same power as using break; but would be much better suited for the very common case of not wanting fallthru. I think it's much more readable, too: makes it very obvious where it falls through. And it's less error prone... no more strange bugs if you accidentally forget to add in a break; statement.

In fact, in my years and years of programming in JavaScript, I have used if/else blocks many many times (some of which could have been switch statements), and only wanted fallthru a handful of times. I think allowing fallthru is fine, but it should be made explicit, rather than implicit.

The only possible argument I can think of in favor of implicit fallthru is using a switch inside a `for` loop:

  for (var i = 0; i < array.length; i += 1) {
      switch (array[i]) {
      case "foo":
          continue;
      }
  }
...but that's actually ridiculous because I'm fairly sure that breaking out of a loop is far more common than continuing. In which case explicit fallthru would be better with loops.

-----

1 point by akkartik 5114 days ago | link

Argh, we're totally talking about different things. And now this thread's gotten hijacked by switch/case/break C whining :)

Part of the problem was that I too was using the wrong terminology. So fuck the names and terms, when I said 'case expressions' I was referring to wart's (def .. :case ..) syntactic sugar to extend any function. This is why I linked to http://en.wikibooks.org/wiki/Haskell/Control_structures#Equa... earlier in the thread. See how I extend keys in http://arclanguage.org/item?id=14244.

-----

1 point by Pauan 5114 days ago | link

Oh, that makes a bit more sense. Technically speaking, Arc's case expression is sorta like guards, though, in the sense of dispatching to different code depending on a condition. You're right that wart's :case is essentially a super nice version of `case`.

Also, what's wrong with `switch` whining? :P This is a JavaScript forum, right? Oh wait...

-----