作为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]
?
答案 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元组。
进一步阅读: