如何在Scala中实现像Int *,String *这样的变种?

时间:2013-01-15 14:03:45

标签: scala

  

可能重复:
  What is the type of a variable-length argument list in 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

但是我找不到任何关于它们的文档。有人能指出一些链接来解释这种类型的功能参数吗?此外,他们被称为参数列表或其他什么?也许我找不到任何东西的原因是因为我用错误的名字搜索?

2 个答案:

答案 0 :(得分:6)

这些是可变长度参数列表(repeated parameters根据规范,Randall正确指出his answer),通常称为“varargs”,K&实现此类功能的RC库函数。

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

Java与语法T... arg具有相同的功能,始终将参数传递为Array[T]。 Scala识别Java varargs并且可以像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
}

答案 1 :(得分:3)

首先,Scala称他们为"repeated parameters,"而不是“varargs。”

与重复形式参数对应的实际参数被收集到由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实现的,所以它们具有固定时间索引访问权限。