web-dev-qa-db-fra.com

Comment formater correctement un composé long si des instructions dans Coffeescript

Si j'avais une déclaration if complexe que je ne voulais pas déborder simplement à des fins esthétiques, quelle serait la façon la plus casher de la casser, car coffeescript interprètera les retours comme le corps de la déclaration dans ce cas?

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

CoffeeScript n'interprétera pas la ligne suivante comme le corps de l'instruction si la ligne se termine par un opérateur, c'est donc ok:

# OK!
if a and
not 
b
  c()

il compile pour

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

afin que votre if puisse être formaté comme

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

ou tout autre schéma de saut de ligne tant que les lignes se terminent par and ou or ou is ou == ou not ou un tel opérateur

Quant à l'indentation, vous pouvez indenter les non-premières lignes de votre if tant que le corps est encore plus indenté:

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

Ce que vous ne pouvez pas faire, c'est ceci:

# 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
86
nicolaskruchten

Cela change quelque peu la signification de votre code, mais peut être utile:

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

Noter la is...isnt chaîne, qui est légitime, tout comme a < b < c est légitime dans CoffeeScript. Bien sûr, la répétition de lame sauce est regrettable, et vous ne voudrez peut-être pas return tout de suite. Une autre approche consisterait à utiliser des trempages pour écrire

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

Le if foo and est un peu inélégant; vous pouvez le supprimer s'il n'y a aucune chance que foo soit undefined.

3
Trevor Burnham

Comme toute autre langue, en ne les ayant pas en premier lieu. Donnez des noms aux différentes parties et traitez-les séparément. Soit en déclarant des prédicats, soit en créant simplement quelques vars booléens.

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
2
John Nilsson

Échapper au saut de ligne me semble le plus lisible:

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

Quand beaucoup de passe-partout bas se produisent, vous devez augmenter le niveau d'abstrait.

Les meilleures solutions sont:

  • utiliser bonnes variables et fonctions nommées

  • règles logiques dans les instructions if/else

L'une des règles logiques est:

(pas A et pas B) == pas (A ou B)

La première façon. 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

Le principal inconvénient de cette méthode est sa lenteur. Nous obtiendrons de meilleures performances si nous utilisons les fonctionnalités des opérateurs and et or et remplaçons les variables par des fonctions:

  • C = A et B

Si A est un faux opérateur andwouldnt appel

  • C = A ou B

Si A est un véritable opérateur orwouldnt appel

La deuxième façon. Fonctions:

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
Nikita