如何在运行时使用隐式?

时间:2015-02-15 04:50:29

标签: scala implicit

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

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

这是否可能,我只是没有正确使用implicits的情况?或者根本不可能?

3 个答案:

答案 0 :(得分:3)

隐式参数在编译时解析。 By-name参数捕获它在传入的范围内访问的值。

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

eval(List(1, 2), test)

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

答案 1 :(得分:1)

如何获取隐式值始终在编译时解决。没有具有隐式参数的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()(_))

这样做你可能无法获得任何收益。

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

答案 2 :(得分:0)

我假设您希望隐式参数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)