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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7938585/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 03:37:54  来源:igfitidea点击:

What does param: _* mean in Scala?

scalasyntaxscala-collections

提问by Chris

Being new to Scala (2.9.1), I have a List[Event]and would like to copy it into a Queue[Event], but the following Syntax yields a Queue[List[Event]]instead:

作为 Scala (2.9.1) 的新手,我有 aList[Event]并想将其复制到 a 中Queue[Event],但以下语法产生 a Queue[List[Event]]

val eventQueue = Queue(events)

For some reason, the following works:

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

val eventQueue = Queue(events : _*)

But I would like to understand what it does, and why it works? I already looked at the signature of the Queue.applyfunction:

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

def apply[A](elems: A*)

And I understand why the first attempt doesn't work, but what's the meaning of the second one? What is :, and _*in this case, and why doesn't the applyfunction just take an Iterable[A]?

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

回答by Ben James

a: Ais type ascription; see What is the purpose of type ascriptions in Scala?

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

: _*is a special instance of type ascription which tells the compiler to treat a single argument of a sequence type as a variable argument sequence, i.e. varargs.

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

It is completely valid to create a Queueusing Queue.applythat has a single element which is a sequence or iterable, so this is exactly what happens when you give a single Iterable[A].

创建具有单个元素的Queueusing是完全有效的,Queue.apply该元素是序列或可迭代的,因此这正是当您提供单个Iterable[A].

回答by Luigi Plinge

This is a special notation that tells the compiler to pass each element as its own argument, rather than all of it as a single argument. See here.

这是一个特殊的符号,它告诉编译器将每个元素作为它自己的参数传递,而不是将所有元素作为单个参数传递。见这里

It is a type annotation that indicates a sequence argumentand is mentioned as an "exception" to the general rule in section 4.6.2 of the language spec, "Repeated Parameters".

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

It is useful when a function takes a variable number of arguments, e.g. a function such as def sum(args: Int*), which can be invoked as sum(1), sum(1,2)etc. If you have a list such as xs = List(1,2,3), you can't pass xsitself, because it is a Listrather than an Int, but you can pass its elements using sum(xs: _*).

当一个函数采用可变数量的参数,它是有用的,例如,功能,例如def sum(args: Int*),它可被调用sum(1)sum(1,2)等等。如果你有一个列表,例如xs = List(1,2,3),你不能传递xs本身,因为它是一个List,而不是一个Int,但您可以使用sum(xs: _*).

回答by Murmel

For Python folks:

对于 Python 的人:

Scala's _*operator is more or less the equivalent of Python's *-operator.

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



Example

例子

Converting the scala example from the linkprovided by Luigi Plinge:

Luigi Plinge提供的链接转换 scala 示例:

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

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

to Python would look like:

到 Python 看起来像:

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

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

and both give the following output:

并且都给出以下输出:

What's
up
doc?

怎么

医生?



The Difference: unpacking positional parameters

区别:解包位置参数

While Python's *-operator can also deal with unpacking of positional parameters/parameters for fixed-arity functions:

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

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

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

8

8

Doing the same with Scala:

用 Scala 做同样的事情:

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

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

will fail:

将失败:

not enough arguments for method multiply: (x: Int, y: Int)Int.
Unspecified value parameter y.

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

But it is possible to achieve the same with scala:

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

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

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

According to Lorrin Nelsonthis is how it works:

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

The first part, f _, is the syntax for a partially applied function in which none of the arguments have been specified. This works as a mechanism to get a hold of the function object. tupled returns a new function which of arity-1 that takes a single arity-n tuple.

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

Futher reading:

延伸阅读: