如何在Coffeescript中正确格式化长复合if语句



如果我有一个复杂的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

如果下一行以操作符结尾,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

或任何其他断行方案,只要行以andoris==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

这在一定程度上改变了代码的含义,但可能有一些用途:

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,则可以丢弃它。

就像其他语言一样,从一开始就没有它们。给不同的部分命名,分开对待。可以声明谓词,也可以创建几个布尔值。

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

转义换行对我来说是最易读的:

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

当出现大量低级别的样板文件时,您应该增加抽象级别

最好的解决方案是:

  • 使用命名好的变量和函数

  • 逻辑规则if/else语句

逻辑规则之一是:

(not A and not B) == not (A or 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

这种方法的主要缺点是速度慢。如果我们使用andor运算符特性,用函数代替变量,我们将获得更好的性能:

  • C = A和B

如果A为假,操作符and 不会调用

  • C = A或B

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

最新更新