2011-01-10 36 views
7

我正在尝试为Scala编写一个性能测量库。我的想法是透明地“标记”部分,以便可以收集执行时间。不幸的是,我无法按照自己的意愿弯曲编译器。如何在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 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) 
    } 
} 

使用time功能直接和编译器能够正确使用返回键入“时间”功能的匿名函数:

val bigString = time('timerBigString) { 
    (1 to 100000).mkString("-") 
} 
println (bigString) 

大,因为它似乎,这种模式有许多缺点:

  • 迫使用户在每次调用
  • 使之更难以做到像预定义的项目级定时器
  • 更先进的东西重复使用相同的符号
  • 不允许图书馆所以这里初始化一次数据结构“timerBigString

谈到mkTimer,这将让我部分应用时功能和重用。我用mkTimer这样的:

val myTimer = mkTimer('aTimer) 
val myString= myTimer { 
    (1 to 100000).mkString("-") 
} 
println (myString) 

但我得到一个编译器错误:

error: type mismatch; 
found : String 
required:() => Nothing 
(1 to 100000).mkString("-") 

我得到同样的错误,如果我行内的柯里:

val timerBigString = time('timerBigString) _ 
val bigString = timerBigString { 
    (1 to 100000).mkString("-") 
} 
println (bigString) 

这个作品,如果我这样做val timerBigString = time('timerBigString) (_: String),但这不是我想要的。我想推迟部分应用函数的打字,直到应用程序。

我断定编译器在我第一次创建时决定部分函数的返回类型,选择“Nothing”是因为它无法做出更好的知情选择。

所以我想我正在寻找的是一种部分应用函数的后期绑定。有没有办法做到这一点?或者,我可以遵循完全不同的路线吗?

好了,感谢您阅读本远

-TeO

回答

7

了以往的模式,当你想“偷懒”仿制药是使用一类具有的适用方法

class Timer(name: Symbol) { 
    def apply[T](op: => T) = time(name)(op) 
} 
def mkTimer(name: Symbol) = new Timer(name) 
+0

点上!谢谢。 – 2011-01-10 12:54:36