Search code examples
scalaimplicit

Implicit def not being found


  val commands = Map("ctrl" -> "^", "anythingToLeft" -> "::")
  val ctrl = "^";
  val anythingToLeft = "::";

  case class Commands(val list: List[String]) {
    def and(that: String) = Commands(that :: list)
  }
  implicit def l(cmd: String) = Commands(cmd :: Nil)

  implicit def f(c: Commands, fun: => Unit) = {
    val launchCommand = c.list.reverse.mkString("") + "::"

    println(launchCommand)
    println(fun);
  }

  f(ctrl and "j", {
    println("ddd")
  })

The above snippet prints the following:

^j::
ddd
()

Which is what I expect. If I do this instead, I get a ';' expected but ',' found error:

ctrl and "j", {
    println("ddd")
  }

Why isn't the compiler adding an implicit call to f in the second version?


Solution

  • First of all, implicit conversions can be used to convert one type to another if an expression does not typecheck. The expression has however to be syntactically valid. This

    ctrl and "j", {
      println("ddd")
    }
    

    is not a syntactically valid expression. Argument lists are not expressions and cannot stand alone, thus you get the complier error.

    Furthermore, implicit conversions may only have one parameter (and possibly further implicit parameters). Your implicit method with two parameters can never be used as a conversion, only as argument to some implicit parameter.

    What you could do is to provide a implicit conversion from a tuple. A conversion won't be applied to a tuple standing alone as conversions are only applied if some expression does not typecheck without it.

    I would suggest that you replace the comma by some other operator and overload that. Something like %%