如何在运行时使用隐式?

How to use an implicit at runtime?

首先,这更多的是为了实验和学习,我知道我可以直接传递参数。

def eval(xs: List[Int], message: => String) = {
  xs.foreach{x=>
    implicit val z = x
    println(message)
  }
}

def test()(implicit x : Int) = {
  if(x == 1) "1" else "2"
}

eval(List(1, 2), test)//error: could not find implicit value for parameter x

这甚至可能吗,我只是没有针对这种情况正确使用隐式?或者根本不可能?

我假设您希望隐式参数 x(在 test 的签名中)由隐式变量 z(在 eval 中)填充。 在这种情况下,z不在x可以看到z的范围内。隐式解析由编译器静态完成,因此运行时数据流永远不会影响它。要了解有关范围的更多信息,this answer 中的 Where do Implicits Come From? 很有帮助。

但是您仍然可以像这样使用 implicit 来达到这个目的。 (我认为这是对 implicit 的误用,所以仅用于演示。)

var z = 0
implicit def zz: Int = z

def eval(xs: List[Int], message: => String) = {
  xs.foreach{ x =>
    z = x
    println(message)
  }
}

def test()(implicit x : Int) = {
  if(x == 1) "1" else "2"
}

eval(List(1, 2), test)

隐式参数在编译时解析。按名称参数捕获它在传入范围内访问的值。

在运行时,没有任何隐含的概念。

eval(List(1, 2), test)

这需要在编译时完全解决。 Scala 编译器必须计算出调用 test 所需的所有参数。它将尝试在调用 eval 范围内找出隐式 Int 变量 。在您的情况下,eval 中定义的隐式值在运行时不会产生任何影响。

如何获取隐式值始终在编译时解决。没有带有隐式参数的 Function 对象。要从具有隐式参数的方法中获取可调用对象,您需要将它们显式化。如果你真的想要,你可以将它包装在另一个使用隐式的方法中:

def eval(xs: List[Int], message: Int => String) = {
  def msg(implicit x: Int) = message(x)
  xs.foreach { x =>
    implicit val z = x
    println(msg)
  }
}

eval(List(1, 2), test()(_))

这样做你可能不会有任何收获。

隐式不能替代传递参数。它们是显式输入您传递的参数的替代方法。但是,实际传递的方式相同。