我从这个问题中得到了以下代码:

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串联在一起,然后呢? : _*是做什么的?

评论

非常感谢您为标题添加(冒号下划线)!

#1 楼

它“ splats” 1序列。
new Elem(prefix: String, label: String, attributes: MetaData, scope: NamespaceBinding,
         child: Node*)


,但是这里只有一个序列,而不是child1child2等,因此可以将结果序列用作构造函数的输入。

快乐编码。


1这在SLS中没有可爱的名字,但下面是详细信息。重要的是要改变Scala将具有重复参数的参数绑定到方法的方式(如上面的Node*所示)。

_*类型注释在“ 4.6.2重复参数”中介绍。 SLS的名称。



参数节的最后一个值参数可以加“ *”,例如(...,x:T *)。这样,方法中这样的重复参数的类型就是序列类型scala.Seq [T]。具有重复参数T *的方法采用可变数量的类型T的参数。也就是说,如果将类型
(p1:T1,...,pn:Tn,ps:S *)U的方法m应用于参数(e1,...,ek),其中k> = n ,则
m在该应用程序中具有类型(p1:T1,...,pn:Tn,ps:S,...,ps0S)U,
,其中k出现n个类型S,其中ps之外的任何参数名称均是新鲜的。此规则的唯一例外是,如果最后一个参数通过_ *类型注释标记为
序列参数。如果将上面的m应用于自变量(e1,...,en,e0:_ *),则该应用程序中m的类型将被视为
(p1:T1,...,pn:Tn ,ps:scala.Seq [S])



评论


我们实际上将其称为“ Smooch运算符”,即使它实际上不是运算符:)

–亨里克·古斯塔夫森(Henrik Gustafsson)
16年4月28日在16:15

在Python中,这称为解压缩

– joshlk
16年5月5日在13:48

序列可以有多长(例如Java varargs)有限制吗?

– qwwqwwq
17年5月3日,下午4:52

#2 楼



child ++ newChild-序列

:-类型归属,有助于编译器理解的提示,该表达式具有什么类型

_*-占位符接受任何值+ vararg运算符

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

评论


您能写更多有关“类型归因”的信息吗?它是什么以及它如何工作?

– amorfis
2011年5月19日7:47

stackoverflow.com/questions/2087250/…

–Vasil Remeniuk
2011年5月19日在9:52

#3 楼

以上所有答案看起来不错,但只需要一个示例即可对此进行解释。
这里是:

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

所以现在我们知道:_*的作用是告诉编译器:请解压缩此参数并将这些元素绑定到函数调用中的vararg参数,而不是将x用作单个参数。

因此,简而言之,:_*可以消除传递参数时的歧义到vararg参数。

评论


这是我一直在寻找的答案。其他的都很棒,但是这个举着这个简单的例子,让我很开心。帽子提示@Keith

–乔治·范丹戈
11月17日15:21

#4 楼

对于像我这样的一些懒惰的人,它只是将Seq转换为varArgs!