8

According to the Scala Spec (2.8), for an implicit to be found it must be defined in local scope, inherited scope, or in a companion object. Given that, it seems to me that the following code should work without an explicit import of the contents of the companion object. I see this used in the Scala library source (eg. CanBuildFrom). It also seems that I should be able to call XX.foo() from outside the definition of the XX class and have my implicit parameter from the companion class used. What am I missing?

object XX {
   implicit def XYZ[T]: (T) => Unit = null
}

class XX {
  // import XX._     // Works with this line uncommented...
  def foo(s: String)(implicit f: (String) => Unit): Unit = {
    if (f == null)
      println("Just: " + s)
    else
      f(s)
  }

  def bar {
    foo("abc"){ s => println("Func: " + s)}
    foo("xyz")  // <-- Compile error here: could not find implicit value for parameter f
  }
}
sellmerfud
  • 340
  • 2
  • 10

1 Answers1

10

I always interpreted the spec to mean that the implicit can be defined in the companion object of the implicit parameter, not the class containing the definition. Something like this:

object ZZ {
   implicit val xyz: ZZ = new ZZ()
}
class ZZ {
  def bar: (String) => Unit = null
}

class XX {
  def foo(s: String)(implicit f: ZZ): Unit = {
    if (f.bar == null)
      println("Just: " + s)
    else
      f.bar(s)
  }

  def bar {
    foo("xyz")
  }
}

It seems clear in Section 7.2 of the spec:

The actual arguments that are eligible to be passed to an implicit parameter of type T fall into two categories. First, eligible are all identifiers x that can be accessed at the point of the method call without a prefix and that denote an implicit definition (§7.1) or an implicit parameter. An eligible identifiermay thus be a local name, or a member of an enclosing template, or it may be have been made accessible without a prefix through an import clause (§4.7). If there are no eligible identifiers under this rule, then, second, eligible are also all implicit members of some object that belongs to the implicit scope of the implicit parameter’s type, T.

Can you quote the part that indicates the companion object of the containing class of the definition?

Mitch Blevins
  • 13,186
  • 3
  • 44
  • 32
  • 1
    Seems I misunderstood which class the companion object had to be associated with. Thanks for clearing it up for me. I'm trying to find a way to define a "default function" that can be passed to another function. But can be overridden by the caller. – sellmerfud Jan 20 '11 at 17:49
  • I assume your "default function" could be implemented as a default argument. http://www.scala-lang.org/node/2075 – Mitch Blevins Jan 20 '11 at 17:55