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

Chr*_*ris 72 syntax scala scala-collections

作为Scala(2.9.1)的新手,我有一个List[Event]并希望将其复制到一个Queue[Event],但是下面的语法产生了一个Queue[List[Event]]代替:

val eventQueue = Queue(events)
Run Code Online (Sandbox Code Playgroud)

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

val eventQueue = Queue(events : _*)
Run Code Online (Sandbox Code Playgroud)

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

def apply[A](elems: A*)
Run Code Online (Sandbox Code Playgroud)

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

Ben*_*mes 75

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

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

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

  • 谢谢你指点我输入归属! (3认同)

Lui*_*hys 70

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

它是一个表示序列参数的类型注释,在语言规范的第4.6.2节"重复参数"中被称为一般规则的"例外".

当一个函数接受可变数量的参数时,它很有用,例如def sum(args: Int*),可以调用的函数sum(1),sum(1,2)等等.如果你有一个列表xs = List(1,2,3),你不能传递xs它自己,因为它是一个List而不是一个Int,但是你可以使用它来传递它的元素sum(xs: _*).

  • @7kemZmani:您必须使用特定的 var-args 类型定义该函数:`def sum(args: Int*)`,并使用通配符“通用”var-args 类型调用它:`val a = sum(xs: _*)`。将 `_*` 视为“我正在传递一个 Int*、一个 String* 或在方法签名中定义的任何内容” (2认同)

Mur*_*mel 15

对于 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: _*)
Run Code Online (Sandbox Code Playgroud)

Python 看起来像:

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

val arr = Array("What's", "up", "doc?")
echo(arr: _*)
Run Code Online (Sandbox Code Playgroud)

并且都给出以下输出:

怎么

医生?


区别:解包位置参数

虽然 Python 的*-operator 也可以处理固定元函数的位置参数/参数的解包:

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

arr = ["What's", "up", "doc?"]
echo(*arr)
Run Code Online (Sandbox Code Playgroud)

8

用 Scala 做同样的事情:

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

val operands = (2, 4)
multiply (operands : _*)
Run Code Online (Sandbox Code Playgroud)

将失败:

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

但是可以使用 Scala 实现相同的目标:

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

val operands = (2, 4)
multiply _ tupled operands
Run Code Online (Sandbox Code Playgroud)

根据Lorrin Nelson 的说法,这就是它的工作原理:

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

延伸阅读: