This page is no longer maintained — Please continue to the home page at www.scala-lang.org

implicit parameter lookup precedence

2 replies
eed3si9n
Joined: 2010-01-24,
User offline. Last seen 42 weeks 6 days ago.
Hi,
I have a question about the implicit parameter lookup precedence,specifically with regards to SLS and Josh's [Implicits without import tax][1] talk from earlier this year.
SLS page 106 states that there are two major categories for looking an implicit parameter of type T.Category 1: local scopeCategory 2: implicit scope (implicit members of the companion objects of the associated types)
We can ignore Category 2 for now.The local scope lookup is described as follows:
> First, eligible are all identifier *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 identifier may 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). 
My question is, if there are several eligible arguments which match the implicit parameter's type in the local scope,
which one is picked?
Josh's talk tells us how it's works in reality:> Implicits defined in current scope (1)> Explicit imports (2)> Wildcard imports (3)> Same scope in other files (4) 
This precedence looks identical to binding ordering described in SLS p. 15.Since binding precedence is about binding a known identifier "x", to a variable "P.A.B.x",I can't see how it could be implied just by the passage I quoted.
Further down the page 106, after defining implicit scope, it says:
> If there are several eligible arguments which match the implicit parameter’s type,> a most specific one will be chosen using the rules of static overloading resolution (§6.26.3).

Does this clause apply both to Category 1 (local scope) and Category 2 (implicit scope)?I admit I don't fully understand 6.26.3, but it seems to be sayingthat specific types and subtypes wins. Nothing about explicit imports etc..
Here's an example:
trait CanFoo[A] {  def foos(x: A): String}
object Def {  implicit object ImportIntFoo extends CanFoo[Int] {    def foos(x: Int) = "ImportIntFoo:" + x.toString  }}
object Main {  def test(): String = {    implicit object LocalIntFoo extends CanFoo[Int] {      def foos(x: Int) = "LocalIntFoo:" + x.toString    }    import Def._            foo(1)  }    def foo[A:CanFoo](x: A): String = implicitly[CanFoo[A]].foos(x)}
println(Main.test)

As Josh's list says, LocalIntFoo wins over ImportedIntFoo.
Thanks,-eugene
  [1]: https://docs.google.com/present/view?id=dfqn4jb_106hq4mvbd8
eed3si9n
Joined: 2010-01-24,
User offline. Last seen 42 weeks 6 days ago.
Re: implicit parameter lookup precedence
Still wondering about this, so [I wrote up some more stuff][1].
-eugene
  [1]: http://eed3si9n.com/revisiting-implicits-without-import-tax
Joshua.Suereth
Joined: 2008-09-02,
User offline. Last seen 32 weeks 5 days ago.
Re: implicit parameter lookup precedence


On Thu, Dec 22, 2011 at 8:43 PM, Eugene Yokota <eed3si9n@gmail.com> wrote:
Hi,
I have a question about the implicit parameter lookup precedence,specifically with regards to SLS and Josh's [Implicits without import tax][1] talk from earlier this year.
SLS page 106 states that there are two major categories for looking an implicit parameter of type T.Category 1: local scopeCategory 2: implicit scope (implicit members of the companion objects of the associated types)
We can ignore Category 2 for now.The local scope lookup is described as follows:
> First, eligible are all identifier *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 identifier may 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). 
My question is, if there are several eligible arguments which match the implicit parameter's type in the local scope,
which one is picked?
You get an "ambiguous call" error, IIRC. 
Josh's talk tells us how it's works in reality: > Implicits defined in current scope (1)> Explicit imports (2)> Wildcard imports (3)> Same scope in other files (4) 
This precedence looks identical to binding ordering described in SLS p. 15. Since binding precedence is about binding a known identifier "x", to a variable "P.A.B.x",I can't see how it could be implied just by the passage I quoted.
Further down the page 106, after defining implicit scope, it says:
> If there are several eligible arguments which match the implicit parameter’s type,> a most specific one will be chosen using the rules of static overloading resolution (§6.26.3).

Does this clause apply both to Category 1 (local scope) and Category 2 (implicit scope)?I admit I don't fully understand 6.26.3, but it seems to be sayingthat specific types and subtypes wins. Nothing about explicit imports etc..
I believe this is only for the second type of import, and a 'recent' change (2.8.x) 
Here's an example:
trait CanFoo[A] {   def foos(x: A): String}
object Def {  implicit object ImportIntFoo extends CanFoo[Int] {     def foos(x: Int) = "ImportIntFoo:" + x.toString  } }
object Main {   def test(): String = {    implicit object LocalIntFoo extends CanFoo[Int] {       def foos(x: Int) = "LocalIntFoo:" + x.toString    }     import Def._            foo(1)   }    def foo[A:CanFoo](x: A): String = implicitly[CanFoo[A]].foos(x) }
println(Main.test)

As Josh's list says, LocalIntFoo wins over ImportedIntFoo.
Thanks,-eugene
  [1]: https://docs.google.com/present/view?id=dfqn4jb_106hq4mvbd8

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland