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
精彩评论