Reputation: 67135
First, this is more for experimentation and learning at this point and I know that I can just pass the parameter in directly.
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
Is this even possible and I am just not using implicits properly for the situation? Or is it not possible at all?
Upvotes: 1
Views: 1438
Reputation: 9151
How to get an implicit value is always resolved at compile time. There's no such thing as a Function
object with an implicit parameter. To get a callable object from a method with implicit parameters, you need to make them explicit. If you really wanted to, you could then wrap that in another method that uses implicits:
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()(_))
You probably won't gain anything by doing that.
Implicits aren't an alternative to passing in parameters. They're an alternative to explicitly typing in the parameters that you're passing in. The actual passing in, however, works the same way.
Upvotes: 1
Reputation: 14082
Implicit parameters are resolved at compile time. By-name parameter captures the values it accesses at the scope where it is passed in.
At runtime, there isn't any implicit concept.
eval(List(1, 2), test)
This needs to be fully resolved at compile time. The Scala compiler has to figure out all the parameters it needs to call test
. It will try to find out a implicit Int
variable at the scope where eval
is called. In your case, the implicit value defined in eval
won't have any effect at runtime.
Upvotes: 3
Reputation: 2193
I assume that you want the implicit parameter x
(in test
's signature) to be filled by the implicit variable z
(in eval
).
In this case, z
is out of the scope within which x
can see z
. Implicit resolution is done statically by compiler, so runtime data flow never affect it. To learn more about the scope, Where do Implicits Come From?
in this answer is helpful.
But you can still use implicit
for that purpose like this. (I think it is misuse of implicit
so only for demonstration.)
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)
Upvotes: 0