Ich habe einmal versucht, darüber zu schreiben, aber ich habe es schließlich aufgegeben, da die Regeln etwas diffus sind. Im Grunde muss man den Dreh raus haben.
Vielleicht ist es am besten, sich darauf zu konzentrieren, wo geschweifte Klammern und Klammern austauschbar verwendet werden können: bei der Übergabe von Parametern an Methodenaufrufe. Sie mayo Klammern durch geschweifte Klammern ersetzen, wenn, und nur wenn, die Methode einen einzelnen Parameter erwartet. Zum Beispiel:
List(1, 2, 3).reduceLeft{_ + _} // valid, single Function2[Int,Int] parameter
List{1, 2, 3}.reduceLeft(_ + _) // invalid, A* vararg parameter
Es gibt jedoch noch mehr, was Sie wissen müssen, um diese Regeln besser zu verstehen.
Verbesserte Kompilierprüfung mit Parens
Die Autoren von Spray empfehlen runde Parens, weil sie eine bessere Kompilierprüfung ermöglichen. Dies ist besonders wichtig für DSLs wie Spray. Durch die Verwendung von Parens teilen Sie dem Compiler mit, dass er nur eine einzige Zeile erhalten soll; wenn Sie ihm also versehentlich zwei oder mehr geben, wird er sich beschweren. Bei geschweiften Klammern ist das nicht der Fall - wenn Sie zum Beispiel irgendwo einen Operator vergessen, wird Ihr Code kompiliert, und Sie erhalten unerwartete Ergebnisse und möglicherweise einen schwer zu findenden Fehler. Das folgende Beispiel ist konstruiert (da die Ausdrücke rein sind und zumindest eine Warnung ausgeben), verdeutlicht aber den Punkt:
method {
1 +
2
3
}
method(
1 +
2
3
)
Die erste kompiliert, die zweite ergibt error: ')' expected but integer literal found
. Der Autor wollte schreiben 1 + 2 + 3
.
Man könnte argumentieren, dass es bei Methoden mit mehreren Parametern und Standardargumenten ähnlich ist; es ist unmöglich, bei der Verwendung von Parens versehentlich ein Komma zur Trennung der Parameter zu vergessen.
Wortbedeutung
Ein wichtiger, oft übersehener Hinweis zur Ausführlichkeit. Die Verwendung geschweifter Klammern führt unweigerlich zu ausführlichem Code, da die Scala-Style-Guide besagt eindeutig, dass schließende geschweifte Klammern in einer eigenen Zeile stehen müssen:
die schließende Klammer steht in einer eigenen Zeile unmittelbar nach dem letzten Zeile der Funktion.
Viele automatische Formatierer, wie z.B. in IntelliJ, führen diese Umformatierung automatisch für Sie durch. Versuchen Sie also, wenn möglich, runde Parens zu verwenden.
Infix-Notation
Bei Verwendung der Infix-Notation, wie List(1,2,3) indexOf (2)
können Sie die Klammern weglassen, wenn es nur einen Parameter gibt, und ihn wie folgt schreiben List(1, 2, 3) indexOf 2
. Dies ist bei der Punktnotation nicht der Fall.
Beachten Sie auch, dass Sie bei einem einzelnen Parameter, der ein Ausdruck mit mehreren Token ist, wie x + 2
o a => a % 2 == 0
müssen Sie Klammern verwenden, um die Grenzen des Ausdrucks anzugeben.
Tupel
Weil man manchmal Klammern weglassen kann, braucht ein Tupel manchmal zusätzliche Klammern wie in ((1, 2))
, und manchmal kann die äußere Klammer weggelassen werden, wie in (1, 2)
. Dies kann zu Verwirrung führen.
Funktion/Teilfunktion-Literale mit case
Scala hat eine Syntax für Funktions- und Teilfunktionsliterale. Sie sieht wie folgt aus:
{
case pattern if guard => statements
case pattern => statements
}
Die einzigen anderen Orte, an denen Sie Folgendes verwenden können case
Aussagen sind mit dem match
y catch
Schlüsselwörter:
object match {
case pattern if guard => statements
case pattern => statements
}
try {
block
} catch {
case pattern if guard => statements
case pattern => statements
} finally {
block
}
Sie können nicht verwenden case
Aussagen in jedem anderen Zusammenhang . Wenn Sie also Folgendes verwenden möchten case
Sie brauchen geschweifte Klammern. Falls Sie sich fragen, was den Unterschied zwischen einer Funktion und einem Teilfunktionsliteral ausmacht, lautet die Antwort: der Kontext. Wenn Scala eine Funktion erwartet, erhalten Sie eine Funktion. Wenn es eine Teilfunktion erwartet, erhalten Sie eine Teilfunktion. Wenn beides erwartet wird, gibt es einen Fehler wegen Mehrdeutigkeit.
Ausdrücke und Blöcke
Klammern können verwendet werden, um Teilausdrücke zu bilden. Geschweifte Klammern können verwendet werden, um Codeblöcke zu bilden (dies ist no ein Funktionsliteral, also hüten Sie sich davor, es wie ein solches zu verwenden). Ein Codeblock besteht aus mehreren Anweisungen, von denen jede eine Importanweisung, eine Deklaration oder ein Ausdruck sein kann. Das geht etwa so:
{
import stuff._
statement ; // ; optional at the end of the line
statement ; statement // not optional here
var x = 0 // declaration
while (x < 10) { x += 1 } // stuff
(x % 5) + 1 // expression
}
( expression )
Wenn Sie also Deklarationen, mehrere Anweisungen, eine import
oder etwas Ähnliches, brauchen Sie geschweifte Klammern. Und da ein Ausdruck eine Anweisung ist, können Klammern innerhalb geschweifter Klammern stehen. Das Interessante ist jedoch, dass Codeblöcke également Ausdrücke, so dass Sie sie überall verwenden können innerhalb einen Ausdruck:
( { var x = 0; while (x < 10) { x += 1}; x } % 5) + 1
Da also Ausdrücke Anweisungen sind und Codeblöcke Ausdrücke sind, ist alles Folgende gültig:
1 // literal
(1) // expression
{1} // block of code
({1}) // expression with a block of code
{(1)} // block of code with an expression
({(1)}) // you get the drift...
Wo sie nicht austauschbar sind
Im Grunde kann man nicht ersetzen {}
con ()
oder umgekehrt irgendwo anders. Zum Beispiel:
while (x < 10) { x += 1 }
Dies ist kein Methodenaufruf, Sie können ihn also nicht auf eine andere Weise schreiben. Nun, Sie können geschweifte Klammern setzen innerhalb die Klammer für die condition
sowie die Verwendung von Klammern innerhalb die geschweiften Klammern für den Codeblock:
while ({x < 10}) { (x += 1) }
Ich hoffe, das hilft.