下面的代码是从this 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!")
}
里面的一切都很清楚,除了这一段:child ++ newChild : _*
它是做什么的?
我知道有Seq[Node]
与另一个Node
连接在一起,然后呢?: _*
是做什么的?
4条答案
按热度按时间j8ag8udp1#
它会“splats“1序列。
查看构造函数签名
称为
但这里只有一个序列,没有
child1
、child2
等,因此这允许将结果序列用作构造器的输入。1在SLS中没有一个可爱的名字,但这里有一些细节。重要的是,它改变了Scala将参数绑定到具有重复参数的方法的方式(如上面的
Node*
所示)。_*
类型注解包含在SLS的“4.6.2重复参数”中。参数段的最后一个值参数可以用“*"作为后缀,例如(...,x:T )。方法中这样一个重复参数的类型是序列类型scala.Seq[T]。具有重复参数T * 的方法采用可变数量的类型T的参数。也就是说,如果方法m具有类型(p1:T1,...,PN:Tn,ps:S)U应用于自变量(e1,. . .,ek),其中k〉= n,则在该应用中m被取为具有类型(p1:T1,...,PN:Tn,ps:S,. . .,ps 0 S)U,出现k ~ n次S类型,其中ps以外的任何参数名都是新的。此规则的唯一例外是最后一个参数通过_ 类型注解标记为序列参数。如果将上面的m应用于参数(e1,. . .,en,e0:_),则在该应用中M的类型被取为(P1:T1,...,PN:Tn,ps:阶数序列[S])**
1l5u6lss2#
child ++ newChild
-序列:
-类型归属,帮助编译器理解表达式类型的提示_*
-接受任何值+ vararg运算符的占位符child ++ newChild : _*
将Seq[Node]
扩展为Node*
(告诉编译器我们更愿意使用varargs,而不是序列)。对于只能接受varargs的方法特别有用。mpbci0fu3#
以上所有答案看起来都很棒,但只需要一个例子来解释这一点。这里是:
现在我们知道
:_*
的作用是告诉编译器:请解压缩此参数并将这些元素绑定到函数调用中的vararg参数,而不是将x作为单个参数。所以简单地说,
:_*
是为了在传递变元给vararg参数时消除歧义。e5nqia274#
对于像我这样的懒人来说,它只是将集合值转换为varArgs!