20 July, 2012

Are you missing the ternary operator in CoffeeScript?

CoffeeScript does not have the ternary operator because the question mark is used for null checks:
if value? then doA() else doB()
Instead of using a ternary, e.g., for conditional assignments, in CoffeeScript you could write:
result = if value > 10 then getA() else getB()
A JavaScript native alternative to the ternary, which also works in CoffeeScript, is the guard syntax:
result = value > 10 && getA() || getB()
If the "guard" before an AND fails, the expression after the AND will not be executed. The whole AND expression will fail then and the OR expression will be considered. And that's it, there you have your new ternary syntax.

But there is more about these AND/OR mechanics. A consecutive OR expression is executed if the previous expression fails (returns a "falsy" value). This also allows for result-dependent sequential execution, such as used when combining sort functions.
sort1 = (a,b) -> byName(a,b)  || byValue(a,b) 
sort2 = (a,b) -> byValue(a,b) || byName(a,b)

data = [
   { name: "a", value: 10 }
   { name: "b", value: 5  }
   { name: "c", value: 5  }

data.sort sort1 # result: a,b,c
data.sort sort2 # result: b,c,a

Please pay attention to how the guard works. In the above example, if the guard evaluates to true AND getA() returns a "falsy" value, then getB() will be returned. This is different from how a real if-then-else or the JavaScript ternary operator works. Falsy values are:
false, 0, "", null, undefined

Instead of using the ternary, either use plain if-then-else in one line or use the guard syntax, but be aware of "falsy" values returned from the guarded expression.

Ciao, Juve