什么是param:_ *在Scala中意味着什么?

时间:2011-10-29 11:22:35

标签: scala syntax scala-collections

作为Scala(2.9.1)的新用户,我有一个List[Event],并希望将其复制到Queue[Event],但以下语法会产生Queue[List[Event]]

val eventQueue = Queue(events)

出于某种原因,以下工作:

val eventQueue = Queue(events : _*)

但我想了解它的作用,以及它的工作原理?我已经查看了Queue.apply函数的签名:

def apply[A](elems: A*)

我理解为什么第一次尝试不起作用,但第二次尝试的含义是什么?在这种情况下,:_*是什么,以及apply函数为什么不采用Iterable[A]

3 个答案:

答案 0 :(得分:66)

a: A是类型归属;见What is the purpose of type ascriptions in Scala?

: _*是类型ascription的特殊实例,它告诉编译器将序列类型的单个参数视为变量参数序列,即varargs。

使用Queue创建一个Queue.apply是完全有效的,Iterable[A]具有一个序列或可迭代的单个元素,所以这正是当你给出一个{{1}}时会发生的事情。

答案 1 :(得分:63)

这是一种特殊的表示法,它告诉编译器将每个元素作为自己的参数传递,而不是将所有元素作为单个参数传递。请参阅here

它是一个类型注释,用于指示序列参数,并且在语言规范“重复参数”的4.6.2节中作为一般规则的“异常”被提及。

当函数采用可变数量的参数时,它很有用,例如def sum(args: Int*)之类的函数,可以调用sum(1)sum(1,2)等。如果您有xs = List(1,2,3)之类的列表,则无法通过xs }本身,因为它是List而不是Int,但您可以使用sum(xs: _*)传递其元素。

答案 2 :(得分:2)

对于Python人员:

Scala的_*运算符或多或少等同于Python的*-operator

示例

link提供的Luigi Plinge转换scala示例:

def echo(args: String*) = 
    for (arg <- args) println(arg)

val arr = Array("What's", "up", "doc?")
echo(arr: _*)

到Python看起来像:

def echo(*args):
    for arg in args:
        print "%s" % arg

arr = ["What's", "up", "doc?"]
echo(*arr)

并且都给出以下输出:

  

什么是
  达
  文档?

差异:解压缩位置参数

虽然Python的* - 运算符也可以处理固定arity函数的位置参数/参数的解包:

def multiply (x, y):
    return x * y

operands = (2, 4)
multiply(*operands)
  

8

对Scala做同样的事情:

def multiply(x:Int, y:Int) = {
    x * y;
}

val operands = (2, 4)
multiply (operands : _*)

会失败:

  

方法乘法的参数不够:(x:Int,y:Int)Int。
  未指定的值参数y。

但是有可能用scala实现相同的目标:

def multiply(x:Int, y:Int) = {
    x*y;
}

val operands = (2, 4)
multiply _ tupled operands

根据Lorrin Nelson,这是如何运作的:

  

第一部分f _是部分应用函数的语法,其中没有指定任何参数。这可以作为获取函数对象的机制。 tupled返回一个新函数,其中arity-1采用单个arity-n元组。

进一步阅读: