J'ai le morceau de code suivant de cette question :
def addChild(n: Node, newChild: Node) = n match {
case Elem(prefix, label, attribs, scope, child @ _*) => Elem(prefix, label, attribs, scope, child ++ newChild : _*)
case _ => error("Can only add children to elements!")
}
Tout y est assez clair, sauf cette pièce: child ++ newChild : _*
Qu'est ce que ça fait?
Je comprends qu'il est Seq[Node]
concaténé avec un autre Node
, et puis? Que fait : _*
-on?
scala
pattern-matching
amorfis
la source
la source
Réponses:
Il "splats" 1 la séquence.
Regardez la signature du constructeur
new Elem(prefix: String, label: String, attributes: MetaData, scope: NamespaceBinding, child: Node*)
qui est appelé comme
new Elem(prefix, label, attributes, scope, child1, child2, ... childN)
mais ici il n'y a qu'une séquence, non
child1
,child2
etc. donc cela permet à la séquence de résultat à utiliser comme entrée au constructeur.Bon codage.
1 Cela n'a pas de nom mignon dans le SLS, mais voici les détails. La chose importante à obtenir est que cela change la façon dont Scala lie les arguments à la méthode avec des paramètres répétés (comme indiqué
Node*
ci-dessus).L'
_*
annotation de type est traitée dans "4.6.2 Paramètres répétés" du SLS.la source
child ++ newChild
- séquence:
- attribution de type, un indice qui aide le compilateur à comprendre, quel type cette expression a-t-elle_*
- espace réservé acceptant n'importe quelle valeur + opérateur varargchild ++ newChild : _*
se développeSeq[Node]
enNode*
(indique au compilateur que nous travaillons plutôt avec un varargs qu'avec une séquence). Particulièrement utile pour les méthodes qui ne peuvent accepter que des varargs.la source
Toutes les réponses ci-dessus sont superbes, mais il suffit d'un échantillon pour l'expliquer. C'est ici :
val x : Seq[Seq[Int]] = Seq(Seq(1),Seq(2)) def f(arg: Seq[Any]*) : Int = { arg.length } f(x) //1 as x is taken as single arg f(x:_*) // 2 as x is "unpacked" as a Seq[Any]*
Alors maintenant, nous savons ce
:_*
qu'il faut dire au compilateur: veuillez décompresser cet argument et lier ces éléments au paramètre vararg dans l'appel de fonction plutôt que de prendre le x comme un seul argument.Donc, en un mot, le
:_*
est de supprimer l'ambiguïté lorsque vous passez l'argument au paramètre vararg.la source
Pour certains paresseux comme moi, cela convertit simplement un Seq en varArgs!
la source