与您的代码的第一个问题是一个小疏忽:你需要导入Numeric
实例的成员,从而使+
到范围(这实际上会带来num.mkNumericOps
进入活动范围,使+
法): 让我们尝试这个:
def defaultParamFunc[B](z: B, y: B)(f: (B, B) => B = (v1: B,v2: B) => { v1 + v2 })(implicit num: Numeric[B]) = {
// Brings `+` into scope.
// Note that you can also just import Numeric.Implicits._ for the same effect
import num._
val ans = f(z,y)
println("ans : " + ans)
ans
}
不幸的是,这仍然不能编译。这里的问题是参数的默认值只能引用早期参数列表中的参数。 由于num
位于最后一个参数列表中,因此无法将其用于默认值。 运气不好。
好了,让我们尝试智取编译器和一分为二的方法,这样我们就可以在参数f
面前的隐含参数num
:
def defaultParamFunc[B](z: B, y: B)(implicit num: Numeric[B]) = new {
// NOTE: using structural typing here is rather inefficient.
// Let's ignore that for now.
import num._
def apply(f: (B, B) => B = (v1: B, v2: B) => { v1 + v2 }) = {
val ans = f(z,y)
println("ans : " + ans)
ans
}
}
甜,它编译。我们在这里完成的是defaultParamFunc
实际上返回一个(伪)函数实例。这个功能是f
作为参数, ,因为我们在defaultParamFunc
身上实例化功能没有任何问题参考num
。
但是,让我们不要太快乐。如果我们试图调用它,而不指定f
参数,编译器是不开心:
scala> defaultParamFunc(5, 7)()
<console>:17: error: not enough arguments for method defaultParamFunc: (implicit num: Numeric[Int])((Int, Int) => Int) => Int{def apply$default$1: (Int, Int) => Int}.
Unspecified value parameter num.
defaultParamFunc(5, 7)()
哎呀。编译器认为空参数列表用于defaultParamFunc
中的第二个(隐式)参数列表,而不是(伪)函数实例的参数列表。
我们必须找到另一种方法,在defaultParamFunc
方法中不需要隐式参数。 Magnet patterns来救援!
trait MyMagnet[B] extends ((B,B) => B)
object MyMagnet {
implicit def fromFunc[B](f: (B, B) => B) = new MyMagnet[B] {
def apply(z: B, y: B): B = {
val ans = f(z,y)
println("ans : " + ans)
ans
}
}
implicit def fromUnit[B](unit: Unit)(implicit num: Numeric[B]) = new MyMagnet[B]{
import num._
def apply(v1: B, v2: B): B = { v1 + v2 }
}
}
def defaultParamFunc[B](z: B, y: B)(magnet: MyMagnet[B]): B = magnet(z, y)
当然,对于如此微小的结果,这是有点做作的。但是,它的工作:
scala> defaultParamFunc(2,3)()
res15: Int = 5
scala> defaultParamFunc(2,3){(x:Int, y:Int) => x*y }
ans : 6
res16: Int = 6
不过,请注意使用磁铁的模式,我们已经失去了类型推断的好处。所以我们不能只是做到以下几点:
scala> defaultParamFunc(2,3)(_ * _)
<console>:18: error: missing parameter type for expanded function ((x$1, x$2) => x$1.$times(x$2))
defaultParamFunc(2,3)(_ * _)
好的。我试过你的代码。这不是编译。当我使用defaultParamFunc(2,3)()它给出了错误'未指定值参数磁铁'。当我尝试defaultParamFunc(2,3){(x:Int,y:Int)=> x * y},我得到了错误'found:(Int,Int)=> Int required:test.ScalaTest.MyMagnet [ Int] 注意:来自Unit的隐式方法在这里是不适用的,因为它在应用程序点之后,它缺少一个明确的结果类型' –
它**不会**编译(在REPL中测试,scala版本2.10.1)。在REPL中,你只需要小心评估'MyMagnet' *特征*和'MyMagnet' *对象*,否则后者不会被视为前者的伴侣对象。但是我可以从错误消息中看到您没有使用REPL。我可以建议的是,你发布的确切代码(如“整个源文件”),所以我可以看到什么是错的。 –
对不起。我是斯卡拉新手。我没有使用REPL。我正在使用SBT运行它。我的scala版本是2.10.3。这里是文件:http://pastebin.com/HDgprLZD –