1

可能重复:
Scala 中可变长度参数列表的类型是什么?

我最近在参数列表上看到了这篇文章:https ://stackoverflow.com/a/4684598/1287554 ,我觉得它真的很有趣。

我也理解下面给出的用例:

def fn(x:Int*) = x.sum                    //> fn: (x: Int*)Int  
fn(1,2,3)                                 //> res0: Int = 6

我看到的明显解释是,它是以下代码的某种语法糖:

def fn(x:List[Int]) = x.sum               //> fn: (x: List[Int])Int
fn(List(1,2,3))                           //> res0: Int = 6

但我找不到任何关于它们的文档。有人可以指出一些解释此类函数参数的链接吗?另外,它们是称为参数列表还是其他名称?也许我找不到任何东西的原因是因为我用错误的名字搜索?

4

2 回答 2

6

这些是可变长度参数列表(根据规范的重复参数,正如Randall在他的回答中正确指出的那样),通常称为“varargs”,是实现此类功能的 K&R C 库函数的名称。

对于 Scala,在 JVM 级别,arg: T*参数作为 传递arg: Seq[T],通常通过WrappedArray.

Java 与语法相同T... arg,总是将参数作为Array[T]. Scala 可以识别 Java 可变参数,并且可以像 Scala 一样调用它们。

Scala varargs 和 Java varargs 之间的一个重要区别是用于调用实现它们的方法的约定不是传递参数,而是传递包含它们的对象。在 Java 中,您可以只传递一个数组:

public void m(String... args)

String[] list = new String[] { "a", "b", "c" };
m(list)

而在 Scala 中,您必须借助一种特殊的语法来明确您的意思:

val list = Seq("a", "b", "c")
m(list: _*)

另外值得注意的是,模式匹配时有一个逆运算符:

list match {
    case Seq(xs @ _*) => xs.size
    case _            => 0
}
于 2013-01-15T14:30:55.403 回答
3

首先,Scala 称它们为“重复参数”,而不是“可变参数”。

一个重复的形参对应的实参被收集到一种特殊的IndexedSeq实现中WrappedArray

scala> def mRP1(ints: Int*): Int = { printf("ints=%s%n", ints); ints.length }
mRP1: (ints: Int*)Int

scala> mRP1(1, 4, 9)
ints=WrappedArray(1, 4, 9)
res0: Int = 3

请注意,因为它们是由它们实现的,所以IndexedSeq它们具有恒定时间的索引访问。

于 2013-01-15T15:04:52.243 回答