How do I properly format long compound if statements in Coffeescript

Coffeescript

Coffeescript Problem Overview


If I had a complex if statement that I did not want to overflow simply for aesthetic purposes, what would be the most kosher way to break it up since coffeescript will interpret returns as the body of the statement in this case?

if (foo is bar.data.stuff and foo isnt bar.data.otherstuff) or (not foo and not bar)
  awesome sauce
else lame sauce

Coffeescript Solutions


Solution 1 - Coffeescript

CoffeeScript will not interpret the next line as the body of the statement if the line ends with an operator, so this is ok:

# OK!
if a and
not 
b
  c()

it compiles to

if (a && !b) {
  c();
}

so your if could be formatted as

# OK!
if (foo is 
bar.data.stuff and 
foo isnt bar.data.otherstuff) or 
(not foo and not bar)
  awesome sauce
else lame sauce

or any other line-breaking scheme so long as the lines end in and or or or is or == or not or some such operator

As to indentation, you can indent the non-first lines of your if so long as the body is even more indented:

# OK!
if (foo is 
  bar.data.stuff and 
  foo isnt bar.data.otherstuff) or 
  (not foo and not bar)
    awesome sauce
else lame sauce

What you cannot do is this:

# BAD
if (foo  #doesn't end on operator!
  is bar.data.stuff and 
  foo isnt bar.data.otherstuff) or 
  (not foo and not bar)
    awesome sauce
else lame sauce

Solution 2 - Coffeescript

This changes your code's meaning somewhat, but may be of some use:

return lame sauce unless foo and bar
if foo is bar.data.stuff isnt bar.data.otherstuff
  awesome sauce
else
  lame sauce

Note the is...isnt chain, which is legit, just as a < b < c is legit in CoffeeScript. Of course, the repetition of lame sauce is unfortunate, and you may not want to return right away. Another approach would be to use soaks to write

data = bar?.data
if foo and foo is data?.stuff isnt data?.otherstuff
  awesome sauce
else
  lame sauce

The if foo and is a little inelegant; you could discard it if there's no chance that foo is undefined.

Solution 3 - Coffeescript

Like any other language, by not having them in the first place. Give names to the different parts an treat them separately. Either by declaring predicates, or by just creating a couple of boolean vars.

bar.isBaz = -> @data.stuff != @data.otherstuff
bar.isAwsome = (foo) -> @isBaz() && @data.stuff == foo
if not bar? or bar.isAwesome foo
  awesome sauce
else lame sauce

Solution 4 - Coffeescript

Escaping the linebreak looks most readable to me:

if (foo is bar.data.stuff and foo isnt bar.data.otherstuff) \
or (not foo and not bar)
  awesome sauce
else lame sauce

Solution 5 - Coffeescript

When a lot of low-level boilerplate occurs you should increase level of abstract.

The best solutions are:

  • to use good named variables and functions

  • logic rules in if/else statements

One of logic rules is:

> (not A and not B) == not (A or B)

The first way. Variables:

isStuff              = foo is bar.data.stuff
isntOtherStuff       = foo isnt bar.data.otherstuff
isStuffNotOtherStuff = isStuff and isntOtherStuff
bothFalse            = not (foo or bar)
if isStuffNotOtherStuff or bothFalse
  awesome sauce
else lame sauce

The main disadvantage of this method is its slowness. We will get better performance if we use and and or operators features and replace variables with functions:

  • C = A and B

If A is false operator and wouldnt call

  • C = A or B

If A is true operator or wouldnt call

The second way. Functions:

isStuff              = -> foo is bar.data.stuff
isntOtherStuff       = -> foo isnt bar.data.otherstuff
isStuffNotOtherStuff = -> do isStuff and do isntOtherStuff
bothFalse            = -> not (foo or bar)
if do isStuffNotOtherStuff or do bothFalse
  awesome sauce
else lame sauce

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionEvanView Question on Stackoverflow
Solution 1 - CoffeescriptnicolaskruchtenView Answer on Stackoverflow
Solution 2 - CoffeescriptTrevor BurnhamView Answer on Stackoverflow
Solution 3 - CoffeescriptJohn NilssonView Answer on Stackoverflow
Solution 4 - CoffeescriptCees TimmermanView Answer on Stackoverflow
Solution 5 - CoffeescriptNikitaView Answer on Stackoverflow