参数:_ *在Scala中是什么意思?


87

作为Scala(2.9.1)的新手,我有个,List[Event]并且想要将其复制到Queue[Event],但是以下语法生成了a Queue[List[Event]]

val eventQueue = Queue(events)

由于某些原因,以下工作原理:

val eventQueue = Queue(events : _*)

但是我想了解它的作用,以及为什么起作用?我已经看过Queue.apply函数的签名:

def apply[A](elems: A*)

我知道为什么第一次尝试不起作用,但是第二次尝试是什么意思?什么是:_*在这种情况下,为什么apply函数不只取一个Iterable[A]

Answers:


93

a: A是类型归属;请参阅Scala中的类型归属的目的是什么?

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

这是完全有效的创建一个Queue使用Queue.apply具有单一元素是一种序列或可迭代的,所以这是当你给一个确切发生了什么Iterable[A]


83

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

它是一种类型注释,它指示序列参数,并在语言规范“重复参数”的4.6.2节中作为一般规则的“例外”提及。

当函数采用可变数量的参数时,这很有用,例如,诸如的函数def sum(args: Int*),可以将其调用为sum(1)sum(1,2)等等。如果具有诸如的列表xs = List(1,2,3),则不能传递xs自身,因为它是一个List而不是一个Int,但是您可以使用传递其元素sum(xs: _*)


def sum(xs: _*)引发“错误:未绑定的通配符类型”
7kemZmani

您的答案很清楚,但这实际上给我造成了更多的混乱,通常在scala中xs: int,xs的类型为int,这就是以上在scala中的语法,其中xs: _*xs被强制转换为其单独的成员。
Rpant

跟随上面的链接,看起来就是这样,类型说明是Java类型转换的scala术语。如果有错,请纠正我。
Rpant

1
@ 7kemZmani:您必须使用特定的var-args类型定义函数:def sum(args: Int*)并使用通配符“ generic” var-args类型:调用它val a = sum(xs: _*)。考虑_*为“我正在传递Int *或String *或方法签名中定义的任何*”
Alfonso Nishikawa

10

对于Python使用者:

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


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的*-operator也可以处理固定参数函数的位置参数/参数的解压缩:

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元组。

进一步阅读:

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.