[英]Tunnel implicit parameter to call-by-name function body
请考虑以下代码段:
object Example {
def run(f: => Unit): Unit = {
implicit val i = 1
f
}
def caller(): Unit =
run {
todo
}
def todo(implicit i: Int): Unit =
println(i)
}
目前没有编译以下消息:
Error:(14, 13) could not find implicit value for parameter i: Int
todo
^
我的问题是可以使隐式参数可用于按名称调用函数体吗?
编辑我尝试使用Alexey Romanov建议的宏实现
import scala.language.experimental.macros
import scala.reflect.macros.whitebox.Context
object Macros {
def run(f: => Unit): Unit = macro runImpl
def runImpl(c : Context)(f: c.Tree) = {
import c.universe._
q"""{
implicit val i: Int = 3
$f
}"""
}
}
object Example extends App {
Macros.run {
todo
}
def todo(implicit i: Int): Unit =
println(i)
}
调试宏我可以看到它被正确扩展为
{
implicit val i: Int = 3
Example.this.todo
}
不幸的是,它没有编译同样的错误,没有发现隐式。
挖掘问题我发现这里的讨论和jira问题https://issues.scala-lang.org/browse/SI-5774
所以问题是一样的:在这种情况下是否有可能将隐式隧道传入todo
函数?
简单地说 - 不。 implicit
要求从代码中可以明显看出发生了什么。 如果你想隐式地将任何东西传递给一个函数,它必须有implicit
参数,而不是f
函数的情况。
这是implicit
的智慧的重要来源: http : //docs.scala-lang.org/tutorials/FAQ/finding-implicits.html
我的问题更多的是关于为什么运行中的隐式定义没有通过隧道传入调用者的运行体
因为这根本不是词法范围的工作方式。 它不在定义主体的范围内。 你有两个很好的选择:
def run(f: Int => Unit) = f(1) run { implicit i => todo // can use i here }
使run
的宏。 这至少应该是一个近似值(改编自SI-5778 ),遗憾的是我现在无法测试它:
object Macros { def run(f: => Unit) = macro runImpl def runImpl(c : Context)(f: c.Tree) = q"""{ implicit val i: Int = 1 // some other implicits $f }""" }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.