Search code examples
scalaimplicit-conversionimplicit

Can an implicit def be used by a function that does not have an implicit param?


I came across this code block on this blog. I want to know how h1("Hello World") is able to compile since h1(children: Frag*).

object TheirCode{
  trait Frag{
    def render: String
  }
  // HTML constructors
  def div(children: Frag*): Frag
  def p(children: Frag*): Frag
  def h1(children: Frag*): Frag
  ...
  implicit def stringFrag(s: String): Frag
}

object MyCode{
  import TheirCode._
  val frag = div(
    h1("Hello World"),
    p("I am a paragraph")
  )
  frag.render // <div><h1>Hello World</h1><p>I am a paragraph</p></div>
}

I'm guessing the implicit def stringFrag automatically converts h1(String) to h1(Frag) but I always thought the method param would need the implicit prefix for this to work (i.e. implicit h1(children: Frag*))


Solution

  • In this case we're not talking about implicit parameters at all, but rather implicit conversions. Whenever the compiler finds an A, but needs a B, it can automatically apply a function of the form implicit def func(_: A): B to make the conversion / assignment possible.

    Simple example:

    implicit def string2int(s: String): Int = s.toInt
    val i: Int = "2"
    

    Note that in order for this to work, you either need to either explicitly import scala.language.implicitConversions or use a compiler flag to enable the feature.