1

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?

Justin Pihony
  • 62,016
  • 17
  • 131
  • 162

3 Answers3

3

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.

Arie Xiao
  • 13,091
  • 3
  • 26
  • 29
1

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.

Dan Getz
  • 7,743
  • 6
  • 29
  • 60
0

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)
Community
  • 1
  • 1
findall
  • 2,178
  • 2
  • 14
  • 21