jusopi
jusopi

Reputation: 6813

Theoretical Coffeescript Switch Statement Conundrum

preface

This probably has no real implementation but after reading another post on coffeescript's 2 switch usages, I decided to play around with it and found this rather odd issue.

coffeescript

type = 'guidance'

s = switch
  when type is 'guidance'
   'g'
  when type is 'vulnerability'
   'v'
  else
   'foo'

console.log s #g

transpiled javascript

var s, type;

type = 'guidance';

s = (function() {
  switch (false) {
    case type !== 'guidance':
     return 'g';
  case type !== 'vulnerability':
     return 'v';
  default:
     return 'foo';
 }
})();

console.log(s); //g

the conundrum

What I don't get is that the case expressions are being compiled to the opposite value. The Coffeescript when type is 'guidance' should transpile to the following javascript case type === 'guidance' right?

If you use s = switch true then the case expressions are rendered correctly case type === 'guidance'. Regardless of the rendered javaScript case expressions, the result is the same.

Upvotes: 2

Views: 186

Answers (2)

Bergi
Bergi

Reputation: 665040

I wouldn't call this an issue, because it works as expected :-)

For the reason, I can only guess (maybe there are some comments in the compiler). It is most likely that they needed to cast all of these expressions to boolean values - they want it to work like an if statement, but switch does use the === operator to compare with the given value. So you can't do

switch (true) {
    case 1: …
    case []: …
    case "true": …
}

because none of those would work, while all of them are truthy values. So you can use the double not operator:

switch (true) {
    case !!( 1 ): …
    case !!( [] ): …
    case !!( "true" ): …
}

and any of those expressions would match true. However, you can reduce your code size a bit by moving the outer ! to the other side of the comparision (!true), and get the equivalent

switch (false) {
    case !( 1 ): …
    case !( [] ): …
    case !( "true" ): …
}

You can see this exact pattern in the coffeescript docs. Now, apparently the compiler is clever enough to compose the ! on an == or === expression to != or !==, but this doesn't work for arbitrary expressions.

If you ask me, they just should've compiled this to a series of if elses.

Upvotes: 3

Pointy
Pointy

Reputation: 413846

For whatever reason, the Coffeescript transpiler generates a switch statement to match the explicit value false, not true. Thus, the case expressions are the opposite of what the when clauses say. When the expression in the when clause is true, the generated switch statement will pick that case because it's looking for the opposite condition to be false.

Upvotes: 1

Related Questions