我在映射带有可选参数的函数时遇到问题。如果参数不是可选的,我会得到相同的类型错误。这是一个简单的例子:
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
的实际类型是什么?
答案 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]