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

发布于 2024-12-12 10:13:48 字数 528 浏览 0 评论 0原文

作为 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] ?

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:

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.apply function:

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 apply function just take an Iterable[A] ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

凹づ凸ル 2024-12-19 10:13:48

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

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

使用 Queue.apply 创建一个具有单个序列或可迭代元素的 Queue 是完全有效的,因此这正是当您给出单个 <代码>可迭代[A]。

a: A is type ascription; see What is the purpose of type ascriptions in 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.

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

无所谓啦 2024-12-19 10:13:48

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

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

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

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 argument and is mentioned as an "exception" to the general rule in section 4.6.2 of the language spec, "Repeated Parameters".

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 xs itself, because it is a List rather than an Int, but you can pass its elements using sum(xs: _*).

ゃ懵逼小萝莉 2024-12-19 10:13:48

对于 Python 人员:

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


示例

链接Luigi Plinge提供:

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

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

Python会看起来like:

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

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

并且都给出以下输出:

什么是
向上
医生?


区别:解包位置参数

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

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

根据 洛林·尼尔森这是它的工作原理:

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

进一步阅读:

For Python folks:

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


Example

Converting the scala example from the link provided by Luigi Plinge:

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

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

to Python would look like:

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:

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

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

8

Doing the same with 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.

But it is possible to achieve the same with scala:

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

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

According to Lorrin Nelson this is how it works:

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.

Futher reading:

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文