考虑以下代码片段:
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 }""" }