使用可选参数映射Scala函数

dkh*_*dkh 5 functional-programming scala map 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)
Run Code Online (Sandbox Code Playgroud)

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

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

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

Lan*_*dei 12

这似乎有效:

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

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


小智 5

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

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

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

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

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

这种类型检查正常,正如其他人所示.

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

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

class Defaults {
  def m(a: Int, b: Int = 3) = a * b
  def a = m(1)
  def b = m(1, 2)
}
Run Code Online (Sandbox Code Playgroud)

然后运行:javap -c默认值