Как правильно форматировать длинные составные, если в Coffeescript
Если бы у меня был сложный оператор if, который я не хотел переполнять просто для эстетических целей, каков был бы самый кошерный способ его разбить, поскольку coffeescript интерпретирует возвраты как тело оператора в этом случае?
if (foo is bar.data.stuff and foo isnt bar.data.otherstuff) or (not foo and not bar)
awesome sauce
else lame sauce
Ответы
Ответ 1
CoffeeScript не будет интерпретировать следующую строку как тело оператора, если строка заканчивается оператором, поэтому это нормально:
# OK!
if a and
not
b
c()
он компилируется в
if (a && !b) {
c();
}
поэтому ваш if
можно отформатировать как
# OK!
if (foo is
bar.data.stuff and
foo isnt bar.data.otherstuff) or
(not foo and not bar)
awesome sauce
else lame sauce
или любой другой схемы разрыва строки, если строки заканчиваются на and
или or
или is
или ==
или not
, или какой-либо такой оператор
Что касается отступов, вы можете отступать от непервых строк вашего if
, пока тело еще больше отступов:
# OK!
if (foo is
bar.data.stuff and
foo isnt bar.data.otherstuff) or
(not foo and not bar)
awesome sauce
else lame sauce
Что вы не можете сделать, так это:
# 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
Ответ 2
Это немного изменяет ваш код, но может быть полезным:
return lame sauce unless foo and bar
if foo is bar.data.stuff isnt bar.data.otherstuff
awesome sauce
else
lame sauce
Обратите внимание на цепочку is...isnt
, которая является законной, так же как a < b < c
является законным в CoffeeScript. Конечно, повторение lame sauce
является неудачным, и вы можете не хотеть return
сразу же. Другим подходом было бы использование soaks для записи
data = bar?.data
if foo and foo is data?.stuff isnt data?.otherstuff
awesome sauce
else
lame sauce
if foo and
немного неэлегантен; вы можете отбросить его, если нет возможности, чтобы foo
был undefined
.
Ответ 3
Как и любой другой язык, не имея их в первую очередь. Дайте имена различным частям обрабатывать их отдельно. Либо объявляя предикаты, либо просто создавая пару логических варов.
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
Ответ 4
Побег над строкой выглядит наиболее читаемым для меня:
if (foo is bar.data.stuff and foo isnt bar.data.otherstuff) \
or (not foo and not bar)
awesome sauce
else lame sauce
Ответ 5
Когда происходит много низкоуровневого шаблона, вы должны увеличить уровень абстрактного.
Лучшие решения:
Один из логических правил:
(не A, а не B) == not (A или B)
Первый способ. Переменные:
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
Основным недостатком этого метода является его медленность. Мы получим лучшую производительность, если будем использовать функции операторов and
и or
и заменим переменные на функции:
Если A
является ложным оператором and
не вызывает
Если A
является истинным оператором or
не будет вызывать
Второй способ. Функции:
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