Ich habe einmal versucht, darüber zu schreiben, aber ich habe am Ende aufgegeben, da die Regeln etwas diffus sind. Grundsätzlich müssen Sie den Dreh raus bekommen.
Vielleicht ist es am besten, sich darauf zu konzentrieren, wo geschweifte Klammern und Klammern austauschbar verwendet werden können: wenn Parameter an Methodenaufrufe übergeben werden. Sie können Klammern nur dann durch geschweifte Klammern ersetzen, 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
Sie müssen jedoch noch mehr wissen, um diese Regeln besser verstehen zu können.
Verbesserte Kompilierungsprüfung mit Parens
Die Autoren von Spray empfehlen runde Parens, da sie die Kompilierungsprüfung verbessern. Dies ist besonders wichtig für DSLs wie Spray. Durch die Verwendung von Parens teilen Sie dem Compiler mit, dass ihm nur eine einzige Zeile zugewiesen werden soll. Wenn Sie es versehentlich zwei oder mehr geben, wird es sich beschweren. Dies ist bei geschweiften Klammern nicht der Fall. Wenn Sie beispielsweise irgendwo einen Operator vergessen, wird Ihr Code kompiliert und Sie erhalten unerwartete Ergebnisse und möglicherweise einen sehr schwer zu findenden Fehler. Das Folgende ist erfunden (da die Ausdrücke rein sind und zumindest eine Warnung geben), macht aber den Punkt:
method {
1 +
2
3
}
method(
1 +
2
3
)
Der erste kompiliert, der zweite gibt error: ')' expected but integer literal found
. Der Autor wollte schreiben 1 + 2 + 3
.
Man könnte argumentieren, dass es für Multi-Parameter-Methoden mit Standardargumenten ähnlich ist; Es ist unmöglich, versehentlich ein Komma zu vergessen, um Parameter zu trennen, wenn Parens verwendet werden.
Ausführlichkeit
Eine wichtige, oft übersehene Anmerkung zur Ausführlichkeit. Die Verwendung von geschweiften Klammern führt unweigerlich zu ausführlichem Code, da im Scala-Styleguide eindeutig angegeben ist, dass das Schließen von geschweiften Klammern in einer eigenen Zeile erfolgen muss:
… Die schließende Klammer befindet sich in einer eigenen Zeile unmittelbar nach der letzten Zeile der Funktion.
Viele automatische Neuformatierer, wie in IntelliJ, führen diese Neuformatierung automatisch für Sie durch. Versuchen Sie also, runde Parens zu verwenden, wenn Sie können.
Infix-Notation
Wenn Sie die Infix-Notation verwenden, List(1,2,3) indexOf (2)
können Sie beispielsweise Klammern weglassen, wenn nur ein Parameter vorhanden ist, und ihn als schreiben List(1, 2, 3) indexOf 2
. Dies ist bei der Punktnotation nicht der Fall.
Beachten Sie auch, dass Sie, wenn Sie einen einzelnen Parameter haben, der ein Ausdruck mit mehreren Token ist, wie x + 2
oder a => a % 2 == 0
, Klammern verwenden müssen, um die Grenzen des Ausdrucks anzugeben.
Tupel
Da Sie manchmal Klammern weglassen können, benötigt ein Tupel manchmal zusätzliche Klammern wie in ((1, 2))
, und manchmal kann die äußere Klammer wie in weggelassen werden (1, 2)
. Dies kann zu Verwirrung führen.
Funktions- / Teilfunktionsliterale mit case
Scala hat eine Syntax für Funktions- und Teilfunktionsliterale. Es sieht aus wie das:
{
case pattern if guard => statements
case pattern => statements
}
Die einzigen anderen Stellen, an denen Sie case
Anweisungen verwenden können, sind die Schlüsselwörter match
und catch
:
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 keine case
Anweisungen in einem anderen Kontext verwenden . Wenn Sie also verwenden möchten case
, benötigen Sie geschweifte Klammern. Wenn Sie sich fragen, was die Unterscheidung zwischen einer Funktion und einer Teilfunktion wörtlich macht, lautet die Antwort: Kontext. Wenn Scala eine Funktion erwartet, erhalten Sie eine Funktion. Wenn eine Teilfunktion erwartet wird, erhalten Sie eine Teilfunktion. Wenn beide erwartet werden, gibt es einen Fehler bezüglich der Mehrdeutigkeit.
Ausdrücke und Blöcke
Klammern können verwendet werden, um Unterausdrücke zu machen. Geschweifte Klammern können verwendet werden, um Codeblöcke zu erstellen (dies ist kein Funktionsliteral, also hüten Sie sich davor, es wie eines zu verwenden). Ein Codeblock besteht aus mehreren Anweisungen, von denen jede eine Importanweisung, eine Deklaration oder ein Ausdruck sein kann. Es geht 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 import
oder ähnliches benötigen, benötigen Sie geschweifte Klammern. Und weil ein Ausdruck eine Aussage ist, können Klammern in geschweiften Klammern stehen. Das Interessante ist jedoch, dass Codeblöcke auch Ausdrücke sind, sodass Sie sie überall in einem Ausdruck verwenden können:
( { var x = 0; while (x < 10) { x += 1}; x } % 5) + 1
Da Ausdrücke Anweisungen und Codeblöcke Ausdrücke sind, gilt Folgendes:
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
Grundsätzlich kann man nicht ersetzen {}
mit ()
oder umgekehrt anderswo. Zum Beispiel:
while (x < 10) { x += 1 }
Dies ist kein Methodenaufruf, daher können Sie ihn nicht auf andere Weise schreiben. Nun, Sie können geschweifte Klammern in die Klammern für das setzen condition
sowie Klammern in die geschweiften Klammern für den Codeblock verwenden:
while ({x < 10}) { (x += 1) }
Ich hoffe, das hilft.