什么`:_ *`(冒号下划线明星)在斯卡拉?

我有这样一个问题的代码:

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 [节点]连接到另一个节点,然后呢? 什么: _*做什么?

提前致谢

它“splats” 1序列。

看看构造函数签名

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

这被称为

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

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

快乐的编码。


1这在SLS中没有可爱的名字,但是这里是细节。 重要的是,它改变了Scala如何用重复的参数来绑定参数(如上面的Node*所示)。

SLS的“4.6.2重复参数”中涵盖了_*类型的注释

参数段的最后一个值参数可以用“*”来表示,例如(…,x:T *)。 方法内部重复参数的类型是序列类型scala.Seq [T]。 重复参数T *的方法采用可变数量的T型参数。 也就是说,如果将类型(p1:T1,…,pn:Tn,ps:S *)U的方法m应用于其中k> = n的自变量(e1,…,ek),则m是(p1:T1,…,pn:Tn,ps:S,…,ps0S)U,其中k个出现的类型S,其中任何超出ps的参数名都是新鲜的。 这个规则的唯一例外是如果最后一个参数被标记为通过_ *类型注释的序列参数。 如果将上面的m应用于参数(e1,…,en,e0:_ *),那么该应用程序中m的类型取为(p1:T1,…,pn:Tn,ps:scala .SEQ [S])

  • child ++ newChild – 序列
  • : – 类型归属,帮助编译器理解的提示,该表达式具有什么类型
  • _* – 占位符接受任何值+可变运算符

child ++ newChild : _*Seq[Node]扩展为Node* (告诉编译器,我们宁愿使用可变参数,而不是序列)。 对于只能接受可变参数的方法特别有用。