367 votes

Quelle est la différence formelle de Scala entre les accolades et les parenthèses, et quand devraient-elles être utilisées?

Quelle est la différence formelle entre le passage d'arguments dans les fonctions de, entre parenthèses, () et accolades {}?

Le sentiment que j'ai eu de la Programmation Scala livre est que la Scala est assez souple et que je devrais utiliser celle que je préfère, mais je trouve que certains cas de la compilation, tandis que d'autres ne le font pas.

Par exemple (juste un exemple; je vous serais reconnaissant de toute réponse qui traite le cas général, pas cet exemple particulier uniquement):

val tupleList = List[(String, String)]()
val filtered = tupleList.takeWhile( case (s1, s2) => s1 == s2 )

=> error: illegal début de la simple expression

val filtered = tupleList.takeWhile{ case (s1, s2) => s1 == s2 }

=> amende.

397voto

Daniel C. Sobral Points 159554

J'ai essayé une fois d'écrire sur ce sujet, mais j'ai donné jusqu'à la fin, et que les règles sont quelque peu diffus. Fondamentalement, vous aurez à obtenir le blocage de celui-ci.

Il est peut être préférable de se concentrer sur l'endroit où accolades et la parenthèse peut être utilisé de façon interchangeable: lors du passage de paramètres aux appels de méthode. Vous pouvez remplacer les parenthèses avec des accolades si, et seulement si, la méthode attend un paramètre unique. Par exemple:

List(1, 2, 3).reduceLeft{_+_} // valid, single Function2[Int,Int] parameter
List{1, 2, 3}.reduceLeft(_+_) // invalid, A* vararg parameter

Cependant, il n'y a plus que vous devez savoir pour mieux comprendre ces règles.

La Notation Infixe

Lors de l'utilisation de 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 de l'écrire comme List(1, 2, 3) indexOf 2. Ce n'est pas le cas de la dot notation.

Notez également que lorsque vous avez un seul paramètre qui est un multi-jeton d'expression, comme x + 2 ou a => a % 2 == 0, vous devez utiliser des parenthèses pour indiquer les limites de l'expression.

Les Tuples

Parce que vous pouvez omettre les parenthèses, parfois un n-uplet a besoin de plus de parenthèses, comme dans l' ((1, 2)), et parfois à l'extérieur des parenthèses peuvent être omises, comme en (1, 2). Cela peut causer de la confusion.

Fonction/Fonction Partielle littéraux

Scala a une syntaxe de la fonction et de la fonction partielle de littéraux. Il ressemble à ceci:

{
    case pattern if guard => statements
    case pattern => statements
}

Les seuls autres endroits où vous pouvez utiliser les instructions case sont à l' match et catch de mots clés:

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 les instructions case dans n'importe quel autre contexte. Donc, si vous souhaitez utiliser case, vous avez besoin d'accolades. Dans le cas où vous vous demandez ce que fait la distinction entre une fonction et fonction partielle, littérale, la réponse est: le contexte. Si Scala s'attend à une fonction, une fonction que vous obtenez. Si elle s'attend à une fonction partielle, vous bénéficiez d'une fonction partielle. Si les deux sont attendus, il donne une erreur à propos de l'ambiguïté.

Les Expressions et les Blocs

Les parenthèses peuvent être utilisées pour faire des sous-expressions. Accolades peuvent être utilisés pour faire des blocs de code (c'est pas une fonction littérale, méfiez-vous donc de tenter de l'utiliser comme une). Un bloc de code se compose de plusieurs états, dont chacun peut être une instruction d'importation, une déclaration ou d'une expression. Il va comme ceci:

{
    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, plusieurs états, un import ou quelque chose comme ça, vous avez besoin d'accolades. Et parce qu'une expression est une instruction, les parenthèses peuvent apparaître à l'intérieur des accolades. Mais la chose intéressante est que les blocs de code sont également des expressions, de sorte que vous pouvez les utiliser n'importe où à l'intérieur d' une expression:

( { var x = 0; while (x < 10) { x += 1}; x } % 5) + 1

Donc, puisque les expressions sont des déclarations, et des blocs de codes sont des expressions, tout ci-dessous 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 {} avec () ou vice versa d'ailleurs. Par exemple:

while (x < 10) { x += 1 }

Ce n'est pas un appel de méthode, de sorte que vous ne pouvez pas l'écrire d'une autre façon. Eh bien, vous pouvez mettre des accolades à l'intérieur de la parenthèse pour l' condition, ainsi que l'utilisation de parenthèses à l'intérieur des accolades pour le bloc de code:

while ({x < 10}) { (x += 1) }

Donc, je espère que cette aide.

63voto

Theo Points 60103

Il ya un couple de différentes règles et des inférences se passe ici: tout d'abord, Scala déduit les accolades lorsqu'un paramètre est une fonction, par exemple, en list.map(_ * 2) les accolades sont présumées, c'est juste une forme courte de list.map({_ * 2}). Deuxièmement, Scala vous permet de passer les parenthèses sur le dernier paramètre de la liste, si le paramètre de la liste a un paramètre et c'est une fonction, alors list.foldLeft(0)(_ + _) peut être écrite de la list.foldLeft(0) { _ + _ } (ou list.foldLeft(0)({_ + _}) si vous voulez être plus explicite).

Toutefois, si vous ajoutez case que vous obtenez, comme d'autres l'ont mentionné, une fonction partielle au lieu d'une fonction, et Scala ne sera pas déduire les accolades partielles de fonctions, list.map(case x => x * 2) ne fonctionne pas, mais les deux list.map({case x => 2 * 2}) et list.map { case x => x * 2 } sera.

23voto

olle kullberg Points 4916

Il y a un effort de la communauté de standardiser l’utilisation d’accolades, parenthèses, voir le Guide de Style de Scala (page 21) : http://www.codecommit.com/scala-style-guide.pdf

La syntaxe recommandée pour les appels de méthodes plus élevés ordre est de toujours utiliser des accolades et d’ignorer le point :

Pour les appels de metod « normal », vous devez utiliser la dot et les parenthèses.

14voto

Lukasz Korzybski Points 3083

Je pense qu'il vaut la peine d'expliquer leur utilisation dans les appels de fonction et pourquoi diverses choses. Comme quelqu'un l'a déjà dit accolades définir un bloc de code, ce qui est aussi une expression qui peut être mis où l'expression est prévue et sera évalué. Lors de l'évaluation, ses instructions sont exécutées et la dernière déclaration de valeur est le résultat de l'ensemble du bloc de l'évaluation (un peu comme en Ruby).

Avoir que l'on peut faire des choses comme:

2 + { 3 }             // res: Int = 5
val x = { 4 }         // res: x: Int = 4
List({1},{2},{3})     // res: List[Int] = List(1,2,3)

Dernier exemple est juste un appel de fonction avec trois paramètres, dont chacun est évalué en premier.

Maintenant à voir comment il fonctionne avec les appels de fonction il est possible de définir une fonction simple que prendre une autre fonction en tant que paramètre.

def foo(f: Int => Unit) = { println("Entering foo"); f(4) }

Pour l'appeler, il nous faut passer de la fonction qui prend un paramètre de type Int, donc on peut utiliser la fonction littérale et de le transmettre à toto:

foo( x => println(x) )

Maintenant comme l'a dit avant nous pouvons utiliser le bloc de code à la place d'une expression donc, nous allons l'utiliser

foo({ x => println(x) })

Ce qui se passe ici est que le code à l'intérieur de {} est évaluée et la valeur de la fonction est retourné comme une valeur du bloc de l'évaluation, cette valeur est ensuite transmis à toto. C'est sémantiquement le même que le précédent appel.

Mais on peut ajouter quelque chose de plus:

foo({ println("Hey"); x => println(x) })

Maintenant, notre bloc de code contient deux états, et parce qu'elle est évaluée avant de foo est exécutée, ce qui se passe c'est que le premier "Hey" est imprimé, puis notre fonction est transmis à toto, "Saisie de foo" est imprimé et enfin "4" est imprimé.

Cela ressemble un peu moche quand même et Scala permet de nous ignorer la parenthèse dans ce cas, nous pouvons donc écrire:

foo { println("Hey"); x => println(x) }

ou

foo { x => println(x) }

Qui ressemble beaucoup plus agréable et est équivalent à l'ancien. Ici encore, le bloc de code est d'abord évaluée et le résultat de l'évaluation (qui est x => println(x)) est passé comme argument à toto.

8voto

fjdumont Points 1015

Parce que vous utilisez `` , vous définissez une fonction partielle et fonctions partielles nécessitent des accolades.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X