VarArgs A * vs Seq [A]参数起作用

时间:2017-09-06 09:08:50

标签: scala

我正在使用Scala 2.11。如果我创建一个像:

这样的函数
def func1 (a: Int* ) : Int = a.reduce(_+_)

我用

来称呼它
func1(1,2,3,4)
// 10
func1(Seq(1,2,3,4) : _*)
//10

这很好。

但是当我尝试定义一个函数文字时,如:

val func2:(Int*) => Int = _.reduce(_+_)

我收到错误说:

<console>:5: error: type mismatch;
 found   : Int* => Int
 required: Seq[Int] => Int
  lazy val $result = INSTANCE.`func2`

为什么在第二种情况下需要Seq[Int]但在第一种情况下却不是,但定义是相同的?

在第一种情况下如何传递varargs,以便可以通过它们调用reduce?

1 个答案:

答案 0 :(得分:5)

Scala区分方法和函数。您的func1是一个参数为repeated的方法,并且这是一个简单的Seq。另一方面,您的func2是一个函数,并且在该上下文中不允许重复参数。

如果编译器需要一个函数但是给它一个方法,它会执行eta-expansion。例如,方法def(s: String) = s变为函数(s: String) => s。我这样说是为了说明方法和功能之间的区别是非常明确和非常重要的。

请注意,我提供的链接表示&#34;函数声明和定义&#34;,这是一种笨拙的命名,因为它实际上是在谈论方法,而不是函数。函数是一个与任何其他值一样的值,它可以是例如保存在一个集合中或从另一个函数返回。方法不能。

最后一条评论我完成了:不要犯一个常见的错误并且认为&#34; def是方法,val是函数&#34;。也可以使用def而不是val来定义函数,在这种情况下,它仍然是函数值,但它在使用时而不是声明点进行评估。区分方法和函数的最佳方法是检查参数:def foo(someParameter: X): Y是一种方法。函数不能有&#34;(someParameter:X)&#34;部分。相反,函数只是一个值,其类型是X =&gt;是的:

// method
def foo(x: X): Y = // some code that returns Y

// function
def foo: X => Y = (x: X) => // some code that returns Y

我故意使用def来表达功能(以防止读者犯下val-def错误),但使用val来定义函数更为常见。< / p>