什么`:_*`(冒号下划线星)在Scala中做什么?

amo*_*fis 186 scala pattern-matching

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

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!")
}
Run Code Online (Sandbox Code Playgroud)

除此之外,其中的所有内容都非常清晰: child ++ newChild : _*

它有什么作用?

我明白有Seq[Node]与另一个连接Node,然后呢?怎么: _*办?

小智 145

它"splats" 1序列.

查看构造函数签名

new Elem(prefix: String, label: String, attributes: MetaData, scope: NamespaceBinding,
         child: Node*)
Run Code Online (Sandbox Code Playgroud)

被称为

new Elem(prefix, label, attributes, scope,
         child1, child2, ... childN)
Run Code Online (Sandbox Code Playgroud)

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

快乐的编码.


1这在SLS中没有可爱的名字,但这里有详细信息.重要的是它改变了Scala如何使用重复参数将参数绑定到方法(如上所示Node*).

_*类型的注释是包括在SLS的"4.6.2重复参数".

参数部分的最后一个值参数可以由"*"表示,例如(...,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次出现类型S,其中超出ps的任何参数名称都是新的.此规则的唯一例外是,如果通过_*类型注释将最后一个参数标记为序列参数.如果上面的m被应用于参数(e1,...,en,e0:_*),则该应用程序中的m的类型被认为是(p1:T1,...,pn:Tn,ps:scala) .SEQ [S])

  • 我们喜欢称它为"Smooch运算符",即使它实际上不是运算符:) (4认同)
  • 在 Python 中,这称为解包 (2认同)

Vas*_*iuk 87

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

child ++ newChild : _*扩展Seq[Node]Node*(告诉编译器我们正在使用varargs而不是序列).对于只能接受varargs的方法特别有用.

  • http://stackoverflow.com/questions/2087250/what-is-the-purpose-of-type-ascription-in-scala (9认同)
  • 你能写更多关于“类型归属”的内容吗?它是什么以及它是如何工作的? (2认同)
  • 很好的答案。因此,通过编写“a: _*”,您可以告诉编译器将“a”视为“_*”的实例,在本例中只是“Node*” (2认同)

Kei*_*ith 18

所有上述答案看起来都很棒,但只需要一个样本来解释这一点.这里是 :

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]*
Run Code Online (Sandbox Code Playgroud)

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

所以简而言之,:_*就是在将参数传递给vararg参数时消除歧义.


man*_*_nz 8

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