Wie formatiere ich lange zusammengesetzte if-Anweisungen in Coffeescript richtig?

68

Wenn ich eine komplexe if-Aussage hätte, die ich nicht nur aus ästhetischen Gründen überlaufen wollte, was wäre der koschere Weg, sie aufzubrechen, da Coffeescript in diesem Fall die Rückgabe als Hauptteil der Aussage interpretiert?

if (foo is bar.data.stuff and foo isnt bar.data.otherstuff) or (not foo and not bar)
  awesome sauce
else lame sauce
Evan
quelle
Wenn not bares eine Möglichkeit in der ersten Klausel gibt (wie die zweite Klausel vorschlägt), dann wird die Referenz bar.dataeinen Fehler verursachen ...
Trevor Burnham

Antworten:

86

CoffeeScript interpretiert die nächste Zeile nicht als Hauptteil der Anweisung, wenn die Zeile mit einem Operator endet. Dies ist also in Ordnung:

# OK!
if a and
not 
b
  c()

es kompiliert zu

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

So können Sie ifals formatiert werden

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

oder ein anderes Zeilenumbruchschema, solange die Zeilen in andoder oroder isoder ==oder notoder einem solchen Operator enden

In Bezug auf die Einrückung können Sie die nicht ersten Zeilen Ihrer Einrückung einrücken if, solange der Körper noch stärker eingerückt ist:

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

Was Sie nicht tun können, ist Folgendes:

# 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
nicolaskruchten
quelle
Danke für die Antwort. Das ist eine großartige Regel, von der ich nicht wusste, dass Operatoren der Schlüssel zum Zeilenumbruch in Coffeescript sind.
Evan
2
Wenn Sie ifden Körper von statmenet nicht "noch mehr" einrücken möchten , können Sie ihn verwenden then, beginnend auf der gleichen Ebene wie if. Es ist meiner Meinung nach besser lesbar.
Dmytro Shevchenko
Ein Hinweis zur Einrückung; Der Körper muss nicht stärker eingerückt sein als die nicht ersten Zeilen des if. Die einzigen Regeln für die korrekte Syntax sind (soweit ich weiß): 1) Der Körper kann nicht die gleiche Einrückung haben wie die erste oder letzte Zeile von ifund 2) Weder der Körper noch eine Zeile von ifkann weniger Einrückungen haben als die erste Zeile der if. Beachten Sie auch, dass Sie in verschiedenen nicht ersten ifZeilen unterschiedliche Einrückungen haben können .
LoPoBo
Normalerweise rücke ich die nicht ersten ifZeilen mit 2 Tabulatoren ein (um besser sichtbar zu machen, dass sie sich weder nach noch innerhalb der befinden if) und den Körper mit 1 Tabulatoren.
LoPoBo
3

Dies ändert die Bedeutung Ihres Codes etwas, kann aber von Nutzen sein:

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

Beachten Sie die is...isntKette, die genauso legitim ist wie a < b < cin CoffeeScript. Natürlich ist die Wiederholung von lame sauceunglücklich, und Sie möchten möglicherweise nicht returnsofort. Ein anderer Ansatz wäre, mit Soaks zu schreiben

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

Das if foo andist ein wenig unelegant; Sie könnten es verwerfen, wenn es keine Chance foogibt undefined.

Trevor Burnham
quelle
2

Wie jede andere Sprache, indem man sie überhaupt nicht hat. Geben Sie den verschiedenen Teilen Namen und behandeln Sie sie separat. Entweder durch Deklarieren von Prädikaten oder durch einfaches Erstellen einiger boolescher 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
John Nilsson
quelle
2
Was ist, wenn die Berechnung einiger Prädikate teuer ist und frühere Prädikate wahrscheinlich bereits das Ergebnis der Anweisung schließen, wenn sie in einem einzelnen Ausdruck verwendet werden?
Halil Özgür
2

Dem Zeilenumbruch zu entkommen, erscheint mir am lesbarsten:

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

Wenn viele Low-Level-Boilerplates auftreten, sollten Sie den Grad der Zusammenfassung erhöhen .

Die besten Lösungen sind:

  • verwenden gut benannten Variablen und Funktionen

  • Logikregeln in if / else- Anweisungen

Eine der logischen Regeln lautet:

(nicht A und nicht B) == nicht (A oder B)

Der erste Weg. Variablen:

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

Der Hauptnachteil dieser Methode ist ihre Langsamkeit. Wir werden eine bessere Leistung erzielen, wenn wir Features verwenden andund orOperatoren verwenden und Variablen durch Funktionen ersetzen:

  • C = A und B.

Wenn Afalsch ist, würde der Operator and nicht aufrufen

  • C = A oder B.

Wenn Adies der or Fall ist, würde der Operator nicht anrufen

Der zweite Weg. Funktionen:

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
Nikita
quelle
Entschuldigung, ich muss das ablehnen. Die Frage war "der koscherste Weg, [eine lange if-Aussage] aufzubrechen", und diese Antwort ist höchst irrelevant.
Ardee Aram