J'ai essayé une fois d'écrire à ce sujet, mais j'ai finalement abandonné, car les règles sont quelque peu diffuses. Fondamentalement, vous devrez vous y familiariser.
Il est peut-être préférable de se concentrer sur les endroits où les accolades et les parenthèses peuvent être utilisées de manière interchangeable: lors du passage des paramètres aux appels de méthode. Vous pouvez remplacer les parenthèses par des accolades si et seulement si la méthode attend un seul paramètre. Par exemple:
List(1, 2, 3).reduceLeft{_ + _} // valid, single Function2[Int,Int] parameter
List{1, 2, 3}.reduceLeft(_ + _) // invalid, A* vararg parameter
Cependant, vous devez en savoir plus pour mieux comprendre ces règles.
Augmentation de la vérification de la compilation avec des parens
Les auteurs de Spray recommandent des parens ronds car ils permettent une vérification accrue de la compilation. Ceci est particulièrement important pour les DSL comme Spray. En utilisant des parens, vous dites au compilateur qu'il ne doit lui être donné qu'une seule ligne; donc si vous lui en donnez accidentellement deux ou plus, il se plaindra. Maintenant, ce n'est pas le cas avec les accolades - si, par exemple, vous oubliez un opérateur quelque part, votre code se compilera et vous obtiendrez des résultats inattendus et potentiellement un bogue très difficile à trouver. Ci-dessous est artificiel (puisque les expressions sont pures et donneront au moins un avertissement), mais fait le point:
method {
1 +
2
3
}
method(
1 +
2
3
)
Le premier compile, le second donne error: ')' expected but integer literal found
. L'auteur a voulu écrire 1 + 2 + 3
.
On pourrait dire que c'est similaire pour les méthodes multi-paramètres avec des arguments par défaut; il est impossible d'oublier accidentellement une virgule pour séparer les paramètres lors de l'utilisation de parens.
Verbosité
Une note importante souvent négligée sur la verbosité. L'utilisation d'accolades conduit inévitablement à un code détaillé car le guide de style Scala indique clairement que la fermeture des accolades doit être sur leur propre ligne:
… L'accolade fermante est sur sa propre ligne immédiatement après la dernière ligne de la fonction.
De nombreux reformatages automatiques, comme dans IntelliJ, effectueront automatiquement ce reformatage pour vous. Essayez donc de vous en tenir à des rondelles rondes lorsque vous le pouvez.
Notation d'infixe
Lorsque vous utilisez la notation infixe, comme List(1,2,3) indexOf (2)
vous pouvez omettre les parenthèses s'il n'y a qu'un seul paramètre et l'écrire comme List(1, 2, 3) indexOf 2
. Ce n'est pas le cas de la notation par points.
Notez également que lorsque vous avez un seul paramètre qui est une expression à plusieurs jetons, comme x + 2
ou a => a % 2 == 0
, vous devez utiliser des parenthèses pour indiquer les limites de l'expression.
Tuples
Parce que vous pouvez parfois omettre des parenthèses, parfois un tuple a besoin de parenthèses supplémentaires comme dans ((1, 2))
, et parfois la parenthèse externe peut être omise, comme dans (1, 2)
. Cela peut être source de confusion.
Littéraux de fonction / fonction partielle avec case
Scala a une syntaxe pour les littéraux de fonction et de fonction partielle. Cela ressemble à ceci:
{
case pattern if guard => statements
case pattern => statements
}
Les seuls autres endroits où vous pouvez utiliser des case
instructions sont les mots clés match
et catch
:
object match {
case pattern if guard => statements
case pattern => statements
}
try {
block
} catch {
case pattern if guard => statements
case pattern => statements
} finally {
block
}
Vous ne pouvez pas utiliser des case
instructions dans un autre contexte . Donc, si vous voulez utiliser case
, vous avez besoin d' appareils orthopédiques. Au cas où vous vous demandez ce qui fait la distinction entre une fonction et une fonction partielle littérale, la réponse est: le contexte. Si Scala attend une fonction, une fonction que vous obtenez. S'il attend une fonction partielle, vous obtenez une fonction partielle. Si les deux sont attendus, cela donne une erreur d'ambiguïté.
Expressions et blocs
Des parenthèses peuvent être utilisées pour créer des sous-expressions. Les accolades peuvent être utilisées pour créer des blocs de code (ce n'est pas une fonction littérale, alors méfiez-vous d'essayer de l'utiliser comme une seule). Un bloc de code se compose de plusieurs instructions, chacune pouvant être une instruction d'importation, une déclaration ou une expression. Ça va comme ça:
{
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 )
Donc, si vous avez besoin de déclarations, de plusieurs déclarations, import
ou quelque chose comme ça, vous avez besoin d'accolades. Et comme une expression est une déclaration, des parenthèses peuvent apparaître entre accolades. Mais la chose intéressante est que les blocs de code sont également des expressions, vous pouvez donc les utiliser n'importe où dans une expression:
( { var x = 0; while (x < 10) { x += 1}; x } % 5) + 1
Donc, comme les expressions sont des instructions et que les blocs de codes sont des expressions, tout ce qui suit est valide:
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...
Où ils ne sont pas interchangeables
Fondamentalement, vous ne pouvez pas remplacer {}
par ()
ou vice versa ailleurs. Par exemple:
while (x < 10) { x += 1 }
Ce n'est pas un appel de méthode, vous ne pouvez donc pas l'écrire autrement. Eh bien, vous pouvez mettre des accolades à l' intérieur des parenthèses pour le condition
, ainsi que des parenthèses à l' intérieur des accolades pour le bloc de code:
while ({x < 10}) { (x += 1) }
J'espère donc que cela aide.