开发者

How do I properly format long compound if statements in Coffeescript

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 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


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.


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


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


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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜