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
點上!謝謝。 – 2011-01-10 12:54:36