如何在scala中使用泛型创建分部函数?
我正试图为Scala编写一个性能度量库。我的想法是透明地“标记”部分,以便收集执行时间。不幸的是,我不能随心所欲地修改编译器 一个公认的人为的例子说明了我的想法:如何在scala中使用泛型创建分部函数?,scala,anonymous-function,currying,Scala,Anonymous Function,Currying,我正试图为Scala编写一个性能度量库。我的想法是透明地“标记”部分,以便收集执行时间。不幸的是,我不能随心所欲地修改编译器 一个公认的人为的例子说明了我的想法: // generate a timing function val myTimer = mkTimer('myTimer) // see how the timing function returns the right type depending on the // type of the function it is pas
// generate a timing function
val myTimer = mkTimer('myTimer)
// see how the timing function returns the right type depending on the
// type of the function it is passed to it
val act = actor {
loop {
receive {
case 'Int =>
val calc = myTimer { (1 to 100000).sum }
val result = calc + 10 // calc must be Int
self reply (result)
case 'String =>
val calc = myTimer { (1 to 100000).mkString }
val result = calc + " String" // calc must be String
self reply (result)
}
现在,这是我得到的最远的结果:
trait Timing {
def time[T <: Any](name: Symbol)(op: => T) :T = {
val start = System.nanoTime
val result = op
val elapsed = System.nanoTime - start
println(name + ": " + elapsed)
result
}
def mkTimer[T <: Any](name: Symbol) : (() => T) => () => T = {
type c = () => T
time(name)(_ : c)
}
}
尽管看起来很好,但这种模式有许多缺点:
- 强制用户在每次调用时重用相同的符号
- 使做更高级的事情变得更加困难,比如预定义的项目级计时器
- 不允许库对“timerBigString”的数据结构进行一次初始化
val myTimer = mkTimer('aTimer)
val myString= myTimer {
(1 to 100000).mkString("-")
}
println (myString)
但我得到一个编译器错误:
error: type mismatch;
found : String
required: () => Nothing
(1 to 100000).mkString("-")
如果我内联currying,我会得到相同的错误:
val timerBigString = time('timerBigString) _
val bigString = timerBigString {
(1 to 100000).mkString("-")
}
println (bigString)
如果我执行val timerBigString=time('timerBigString)(\uu:String)
,这就行了,但这不是我想要的。我想将部分应用函数的键入推迟到应用程序
我的结论是,当我第一次创建分部函数时,编译器正在决定它的返回类型,选择“Nothing”,因为它不能做出更好的选择
所以我想我要寻找的是一种部分应用函数的后期绑定。有没有办法做到这一点?或者也许我可以走一条完全不同的道路
好的,谢谢你读到这里
-teo当您想要“懒惰”泛型时,通常的模式是使用带有apply方法的类
class Timer(name: Symbol) {
def apply[T](op: => T) = time(name)(op)
}
def mkTimer(name: Symbol) = new Timer(name)
class Timer(name: Symbol) {
def apply[T](op: => T) = time(name)(op)
}
def mkTimer(name: Symbol) = new Timer(name)