在 Scala 中从 seq 到 _*

From seq to _* in Scala

有谁知道我们如何以自动方式从任何 Seq 转换为 _*?每次我们有一个 Seq 和一个方法使用 vararg 类型的参数时,强制类型是非常麻烦的。

def mean[T: Numeric](elems: T*): Double
...
elems = Seq(1.0, 2.0, 3.0)
mean(elems) // this doesn't compiles
mean(elems: _*) // this compiles but it is cumbersome

这是唯一的方法。这就是为什么可以说可变参数最好只用在库的 public 接口上,即使那样,尤其是当您认为调用者将使用字面指定的元素而不是集合进行调用时。如果一个方法可能会在集合参数上被调用,可变参数可能会适得其反,正如您已经注意到的那样,它的目标是减少语法噪音。

如果该方法不是通用的,您可以添加重载:

def mean(elems: Seq[Double]): Double = ...
def mean(elems: Double*)(implicit d: DummyImplicit): Double = mean(elems)

唉,这种情况不行:

scala> object X { def f[T: Numeric](x: T*) = x; def f[T: Numeric](x: Seq[T])(implicit d: DummyImplicit) = x }
defined module X

scala> X.f(Seq(1, 2))
<console>:9: error: ambiguous reference to overloaded definition, both method f in object X of type [T](x: Seq[T])(implicit evidence: Numeric[T], implicit d: DummyImplicit)Seq[T] and  method f in object X of type [T](x: T*)(implicit evidence: Numeric[T])Seq[T] match argument types (Seq[Int])
              X.f(Seq(1, 2))
                ^

因为编译器认为 T 可能是 IntSeq[Int],并在检查隐式是否可用于两者之前停止(至少在 Scala 2.10 中)。