55 votes

Les "postfix ops" de Scala

J'ai cherché une demi-heure et je n'arrive toujours pas à comprendre.

Dans SIP: Modularizing Language Features , un certain nombre de fonctionnalités nécessiteront un "activation" explicite dans Scala 2.10 ( import language.feature ). Parmi eux, il y a postfixOps , pour lequel je ne peux pas trouver de référence nulle part. Qu'est-ce que cette fonctionnalité permet exactement?

58voto

Kim Stebel Points 22873

Il vous permet d'utiliser l'opérateur de syntaxe dans postfix position. Par exemple

List(1,2,3) tail

plutôt que de

List(1,2,3).tail

Dans ce inoffensifs exemple, il n'est pas un problème, mais il peut conduire à des ambiguïtés. Ce ne sera pas de la compilation:

val appender:List[Int] => List[Int] = List(1,2,3) ::: //add ; here
List(3,4,5).foreach {println}

Et le message d'erreur n'est pas très utile:

    value ::: is not a member of Unit

Il tente d'appeler l' ::: méthode sur le résultat de l' foreach appel, qui est de type Unit. Ce n'est probablement pas ce que le programmeur a prévu. Pour obtenir le résultat correct, vous devez insérer un point-virgule après la première ligne.

31voto

Alex Points 88

La réponse la plus simple que jamais:

Déposer point de méthodes sans paramètre est OBSOLÈTE!

List(1,2,3) reverse //is bad style and will lead to unpredicted behaviour
List(1,2,3) map(_*2) reverse //bad too, because reverse can take first method call from the next line (details below)

OK pour déposer point des méthodes qui prennent un paramètre d' ordre supérieur de la fonction comme map, filter, le comte et être en sécurité! Aussi, purement fonctionnel, les méthodes de type zip.

List(1,2,3) map(_*2) filter(_>2)
(List(1,2,3) map(_*2)).reverse //safe and good
List(1,3,5) zip List(2,4,6)

Réponse longue POURQUOI

case class MyBool(x: Boolean) {
  def !!! = MyBool(!x) //postfix
  def or(other: MyBool): MyBool = if(x) other else this //infix
  def justMethod0() = this //method with empty parameters
  def justMethod2(a: MyBool, b: MyBool) = this //method with two or more
  override def toString = if(x) "true" else "false"
}

1) Postfix l'opérateur est en fait un appel de méthode sans paramètres (a!==un.!) et sans crochets. (considéré comme dangereux et obsolète)

val b1 = MyBool(false) !!!
List(1,2,3) head

2) Postfix opérateur est de la méthode, qui devrait mettre fin à la ligne, sinon il sera considéré comme infixe.

val b1 = MyBool(true) no! no! //ERROR
//is actually parsed like
val b2 = MyBool(true).no!(no!) //(no!) is unknown identifier
//as bad as
Vector(1,2,3) toList map(_*2) //ERROR

3) opérateur Infixe est une méthode avec un paramètre, qui peut être appelé sans dot et les parenthèses. Seulement pour purement fonctionnelle, méthodes

val c1 = MyBool(true) or b1 or MyBool(true)
val c2 = MyBool(true).or(b1).or(MyBool(true))
c1 == c2

4) Méthode avec un ou plusieurs paramètres de la chaîne sans dot si vous l'appelez, avec des paramètres. def a(), def(x), def(x,y) Mais vous ne devez le faire que pour les méthodes qui utilisent l' ordre supérieur de la fonction en tant que paramètre!

val d1 = MyBool(true) justMethod2(b1, c1) or b1 justMethod0() justMethod2(c1, b1)
//yes, it works, but it may be confusing idea
val d2 = MyBool(true).justMethod2(b1,c1).or(b1).justMethod0().justMethod2(c1, b1)
d1 == d2
//looks familiar? This is where it should be used:
List(1,2,3) filter(_>1) map(_*2)

Exemple de mises en garde:

avertissement: il y avait 1 autodérision avertissement(s); re-courir avec autodérision pour plus de détails avertissement: postfix opérateur de queue doit être activé en faisant la valeur implicite de la scala.de langue.postfixOps visible. Cela peut être réalisé par l'ajout de l'importation de la clause d'importation scala.de langue.postfixOps " ou par le réglage de l'option de compilateur -langue:postfixOps. Voir la Scala de docs pour la valeur de la scala.de langue.postfixOps pour une discussion pourquoi la fonction doit être explicitement activé.

5voto

Régis Jean-Gilles Points 14463

Il fait référence à la possibilité d'appeler une méthode nullary (sans liste d'arguments ou liste d'arguments vide) en tant qu'opérateur postfix:

Par exemple:

 case class MyBool(value: Boolean) {
    def negated = new MyBool(!value)
}
val b1 = MyBool( true )
val b2 = b1 negated // Same as b1.negated
 

Voir: http://www.scala-lang.org/node/118

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