[英]How do I create a partial function with generics in scala?
I'm trying to write a performance measurements library for Scala. 我正在尝试为Scala编写性能测量库。 My idea is to transparently 'mark' sections so that the execution time can be collected. 我的想法是透明地“标记”部分,以便可以收集执行时间。 Unfortunately I wasn't able to bend the compiler to my will. 不幸的是我无法按照我的意愿弯曲编译器。
An admittedly contrived example of what I have in mind: 一个公认的例子,说明了我的想法:
// 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)
}
Now, this is the farthest I got: 现在,这是我得到的最远的:
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)
}
}
Using the time
function directly works and the compiler correctly uses the return type of the anonymous function to type the 'time' function: 使用time
函数直接工作,编译器正确使用匿名函数的返回类型来键入'time'函数:
val bigString = time('timerBigString) {
(1 to 100000).mkString("-")
}
println (bigString)
Great as it seems, this pattern has a number of shortcomings: 看起来很棒,这种模式有许多缺点:
So here it comes mkTimer, that would allow me to partially apply the time function and reuse it. 所以这里是mkTimer,它允许我部分应用时间函数并重用它。 I use mkTimer like this: 我像这样使用mkTimer:
val myTimer = mkTimer('aTimer)
val myString= myTimer {
(1 to 100000).mkString("-")
}
println (myString)
But I get a compiler error: 但是我收到编译错误:
error: type mismatch;
found : String
required: () => Nothing
(1 to 100000).mkString("-")
I get the same error if I inline the currying: 如果我内联curry,我会得到同样的错误:
val timerBigString = time('timerBigString) _
val bigString = timerBigString {
(1 to 100000).mkString("-")
}
println (bigString)
This works if I do val timerBigString = time('timerBigString) (_: String)
, but this is not what I want. 如果我执行val timerBigString = time('timerBigString) (_: String)
,这是有效的,但这不是我想要的。 I'd like to defer typing of the partially applied function until application. 我想推迟部分应用函数的输入直到应用程序。
I conclude that the compiler is deciding the return type of the partial function when I first create it, chosing "Nothing" because it can't make a better informed choice. 我得出结论,编译器在我第一次创建它时决定部分函数的返回类型,选择“Nothing”因为它无法做出更明智的选择。
So I guess what I'm looking for is a sort of late-binding of the partially applied function. 所以我想我正在寻找的是一种对部分应用函数的后期绑定。 Is there any way to do this? 有没有办法做到这一点? Or maybe is there a completely different path I could follow? 或许我可以遵循一条完全不同的道路?
Well, thanks for reading this far 好吧,感谢您阅读这篇文章
-teo -TeO
The usual pattern when you want "lazy" generics is to use a class with an apply method 当你想要“懒惰”泛型时,通常的模式是使用带有apply方法的类
class Timer(name: Symbol) {
def apply[T](op: => T) = time(name)(op)
}
def mkTimer(name: Symbol) = new Timer(name)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.