5

Consider the following code:

class A { def print = println("A") }
class B extends A { override def print = println("B") }

def foo(implicit a: A) = a.print

def bar(implicit a: A) = {
  implicit val b = new B
  foo
}

bar(new A) // B

I am wondering why calling foo in bar isn't raising an ambiguous implicit values error. Of course

implicit val b: A = new B

will raise that error. Why does foo pick the implicit b and not the implicit a? Or even more general: What are the rules what will be picked?

EDIT:
Due to my comment-conversation with Ivan I want to clarify: I would know the answer to my question if I named the local implicit val the same way as the implicit method parameter.

def bar(implicit a: A) = {
  implicit val a = new B
  foo
}

Then only the local val a is in scope which scope-overrides the method parameter because they have the same name.

kiritsuku
  • 51,545
  • 18
  • 109
  • 133
Peter Schmitz
  • 5,734
  • 4
  • 24
  • 48

1 Answers1

1

Note: I'm probably vastly oversimplying things, but in testing it seemed like the following.

It's because the 2nd one is in an inner scope, so it has precedence. Its the same thing that happens with

object test {
 val a = 5
 def test(i: Int) = {
   val a  = 6
   i + a
 }
}

In this case you would expect a to be 6 inside the function. The following is similar.

object test {
  implicit val i = 5; 
  { 
    implicit val b = 6; 
    test
  } 
  def test(implicit ii:Int) = println(ii)
} 

Updated from comment.

scala> def test(a: Int) = {val a = 5; a }
test: (a: Int)Int

scala> test(6)
res1: Int = 5
Ivan Meredith
  • 2,212
  • 12
  • 13
  • Interesting viewpoint! scoping: yes, I though about it, but in my understanding method parameters are in the same scope as local vals/vars defined in the same method. Your examples put them out of scope. Then precedence is very clear to me. Now I am curious: Are method parameters not in the same scope as local method vals/vars or is it an special treatment for implicits in scala? – Peter Schmitz Nov 23 '12 at 10:04
  • I updated my answer. local vals take precendence over method parameters. – Ivan Meredith Nov 23 '12 at 10:08
  • I see: local vals take precedence over method parameters when they have the same name (trivial) and analogous to that local implicits take precedence over method parameter implicits when they both fit and have the same name. – Peter Schmitz Nov 23 '12 at 10:16
  • 1
    But, in my case they don´t have the same name and if I only change the type annotation from `implicit val b: B = new B` to `implicit val b: A = new B` and error is raised, although I haven´t change something that has to do with scoping. For me it seems to deal with subclassing and not only with scoping (which is also important, you pointed out) – Peter Schmitz Nov 23 '12 at 10:20