Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在scala中使用泛型创建分部函数?_Scala_Anonymous Function_Currying - Fatal编程技术网

如何在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

我正试图为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)
  }
}
尽管看起来很好,但这种模式有许多缺点:

  • 强制用户在每次调用时重用相同的符号
  • 使做更高级的事情变得更加困难,比如预定义的项目级计时器
  • 不允许库对“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("-")
如果我内联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)