Jacek Kołodziejczyk
Jacek Kołodziejczyk

Reputation: 634

Why implicit conversion of a code block does not work

Could you please explain why the second call to listen method does not work and suggest a solution to make it work?

object Example extends App {
  case class Event(kind: Int)
  trait Listener { def handle(e: Event) }
  val listeners = scala.collection.mutable.Map[Int, Listener]()
  def emit(e: Event) = listeners.get(e.kind).foreach(_.handle(e))
  def listen(kind: Int)(f: (Event) => Unit) {
    val l = new Listener() { override def handle(e: Event) = f(e) }
    listeners += kind -> l
  }
  implicit def unit2EventUnit(f: => Unit) = (e: Event) => f

  // This works as expected
  println("1")
  listen(1) { e: Event => println("a"); println("b") }
  println("2")
  emit(new Event(1))
  println("3")

  // Why this does not work? "c" should appear between "4" and "d", not "3" and "4"
  listen(2) { println("c"); println("d") }
  println("4")
  emit(new Event(2))
  println("5")
}

I know this would work:

implicit def unit2EventUnit2(f: () => Unit) = (e: Event) => f()
listen(2) { () => println("c"); println("d") }

But that would be simpler to write:

listen(2) { println("c"); println("d") }

Upvotes: 0

Views: 127

Answers (1)

drexin
drexin

Reputation: 24403

The compiler only sees a block in listen(2) { () => println("c"); println("d") }. This block however does not match the signature of the listen function, but it returns a Unit and there is an implicit conversion from Unit to Event => Unit, so it takes the last expression in the block and applies the conversion. That's why you get this result. I don't see an obvious solution to this, but you could just ignore the parameter in your function and write it as

listen(2) { _ => println("c"); println("d") }

Then you also don't need the implicit conversion. This kind of conversions shouldn't be used anyway, because they make your code hard to reason about for people who don't know of the conversion and also it is a possible source for unexpected behavior.

Upvotes: 3

Related Questions