我有下面这个问题的一段代码:

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!")
}

其中的一切都很清楚,除了这一部分:child ++ newChild: _*

它能做什么?

我知道有Seq[Node]连接到另一个Node,然后?_*做什么?


它“splat”1序列。

查看构造函数签名

new Elem(prefix: String, label: String, attributes: MetaData, scope: NamespaceBinding,
         child: Node*)

它被称为

new Elem(prefix, label, attributes, scope,
         child1, child2, ... childN)

但是这里只有一个序列,而不是child1、child2等,所以这允许结果序列用作构造函数的输入。


这在SLS中没有一个可爱的名字,但这里是细节。重要的是,它改变了Scala使用重复参数将参数绑定到方法的方式(如上面的Node*所示)。

_*类型注释在SLS的“4.6.2重复参数”中包含。

The last value parameter of a parameter section may be suffixed by “*”, e.g. (..., x:T ). The type of such a repeated parameter inside the method is then the sequence type scala.Seq[T]. Methods with repeated parameters T * take a variable number of arguments of type T . That is, if a method m with type (p1 : T1, . . . , pn : Tn,ps : S)U is applied to arguments (e1, . . . , ek) where k >= n, then m is taken in that application to have type (p1 : T1, . . . , pn : Tn,ps : S, . . . , ps0S)U, with k ¡ n occurrences of type S where any parameter names beyond ps are fresh. The only exception to this rule is if the last argument is marked to be a sequence argument via a _ type annotation. If m above is applied to arguments (e1, . . . , en,e0 : _), then the type of m in that application is taken to be (p1 : T1, . . . , pn : Tn,ps :scala.Seq[S])**


child ++ newChild -序列 : - type归属,一个帮助编译器理解表达式的类型的提示 _* -接受任何值的占位符+可变参数运算符

child ++ newChild: _*将Seq[Node]展开为Node*(告诉编译器我们正在处理一个变参数,而不是一个序列)。对于只能接受可变参数的方法尤其有用。


上面所有的答案看起来都很棒,但只需要一个例子来解释这一点。 下面就是:

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]*

现在我们知道了:_*的作用是告诉编译器:请解包这个参数,并在函数调用中将这些元素绑定到变量形参,而不是将x作为一个单独的参数。

因此,简单地说,:_*是在将参数传递给可变参数时消除歧义。


对于像我这样的懒人来说,它只是将集合值转换为varArgs!