使用可选参数映射Scala函数

时间:2011-04-05 05:51:00

标签: scala map functional-programming optional-parameters

我在映射带有可选参数的函数时遇到问题。如果参数不是可选的,我会得到相同的类型错误。这是一个简单的例子:

scala> def multiple(m: Int, n: Int = 2) = m * n
multiple: (m: Int,n: Int)Int

scala> multiple(5)
res0: Int = 10

scala> multiple(5, 7)
res1: Int = 35

scala> (1 to 10).map(multiple)
<console>:7: error: type mismatch;
 found   : (Int, Int) => Int
 required: (Int) => ?
       (1 to 10).map(multiple)

这是让它工作的一种方法,但它需要重复默认参数,这是一个维护噩梦:

scala> (1 to 5).map { n => multiple(n, 2) } 
res6: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4, 6, 8, 10)

有更好的方法吗?更一般地说,为什么带有可选参数的函数看起来与参数不可选时的类型相同? multiple的实际类型是什么?

4 个答案:

答案 0 :(得分:12)

这似乎有效:

(1 to 10).map(multiple(_)) 

//res0: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)

答案 1 :(得分:5)

当在期望函数的情况下使用时,Scala会将方法“提升”到FunctionN [T1,...,R]。

在这种情况下,因为多个参数需要2个参数,所以它有效地提升为:

(1 to 10).map(new Function2[Int,Int,Int]{ def apply(v1: Int, v2: Int) = multiple(v1, v2) })

即使原始方法有默认参数,FunctionN对象也没有。现在应该清楚类型错误。当使用多个(_)时,这是对具有单个参数的多个调用,其中第二个是默认值,因此被视为:

(1 to 10).map(new Function1[Int,Int]{ def apply(v1: Int) = multiple(v1) })

此类型检查正常,正如其他人所示。

请注意,(multiple _)与multiple(_)不同。前者表示多个所有参数都是野蛮的,因此是一个Function2,而后者是将多个应用于一个外卡参数,导致另一个参数默认为在该点,因此是功能1。

默认值是在编译时通过引入一个返回默认值的新方法实现的。在调用默认方法的情况下,如果缺少参数,则在将调用添加到方法本身之前,编译器将向默认参数的额外方法添加必要的调用。这意味着该方法本身被编译为代码,该代码本身不知道默认参数。要查看此内容,请编译以下示例类:

class Defaults {
  def m(a: Int, b: Int = 3) = a * b
  def a = m(1)
  def b = m(1, 2)
}

然后运行:javap -c Defaults

答案 2 :(得分:1)

能够写

scala> (1 to 10).map(multiple)

您可以传递部分应用的功能

def multiple(m: Int, n: Int) = m * n
val mul2 = multiple(_: Int, 2)
(1 to 10) map mul2

答案 3 :(得分:0)

  

这是让它运作的一种方法,但它   需要重复默认值   论证,这是一种维护   恶梦:

顺便说一句,这也有效:

scala> (1 to 5).map { n => multiple(n) } 
res0: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4, 6, 8, 10)

所以你不需要重复默认参数;)[Scala 2.9.0.RC1]