Scala call-by-name constructor parameter in implicit class

空扰寡人 提交于 2019-12-11 04:09:16

问题


The following code does not compile. Desired is to have a call-by-name constructor parameter in an implicit class as illustrated here,

def f(n: Int) = (1 to n) product

implicit class RichElapsed[A](val f: => A) extends AnyVal {

  def elapsed(): (A, Double) = {
    val start = System.nanoTime()
    val res = f
    val end = System.nanoTime()

    (res, (end-start)/1e6)
  }

}

where a call

val (res, time) = f(3).elapsed
res: Int = 6
time: Double = 123.0

This error is reported in REPL,

<console>:1: error: `val' parameters may not be call-by-name
       implicit class RichElapsed[A](val f: => A) extends AnyVal {

Thus to ask how RichElapsed class could be refactored.

Thanks in Advance.


回答1:


Peter Schmitz's solution to simply drop the val (along with the hope of turning RichElapsed into a value class) is certainly the simplest and least intrusive thing to do.

If you really feel like you need a value class, another alternative is this:

class RichElapsed[A](val f: () => A) extends AnyVal {

  def elapsed(): (A, Double) = {
    val start = System.nanoTime()
    val res = f()
    val end = System.nanoTime()

    (res, (end-start)/1e6)
  }
}

implicit def toRichElapsed[A]( f: => A ) = new RichElapsed[A](() => f )

Note that while using a value class as above allows to remove the instantiation of a temporary RichElapsed instance, there is still some wrapping going on (both with my solution and with Peter Schmitz's solution). Namely, the body passed by name as f is wrapped into a function instance (in Peter Schmitz's case this is not apparent in the code but will happen anyway under the hood). If you want to remove this wrapping too, I believe the only solution would be to use a macro.




回答2:


Do it without val as the error messages demands and then you also have to abandon the AnyVal since a value class needs to have exactly one public val:

implicit class RichElapsed[A](f: => A)


来源:https://stackoverflow.com/questions/23103947/scala-call-by-name-constructor-parameter-in-implicit-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!