1
votes

I have a Scala code similar to the code below. There is an implicit defined at the class / object level and I want to 'override' it with an implicit defined in the method. (If you really need to know, I need to change my ExecutionContext specially for the method in question).

In this example, I want to use b as the implicit for Int in the scope of the bar method. How can I do this?

object Foo {
  implicit val a: Int = 1
  def bar: Int = { // Didn't pass implicit Int parameter
    implicit val b: Int = 2
    implicitly[Int]
  }
}

This complains with

error: ambiguous implicit values: both value a in object Foo of type Int and value b of type Int match expected type Int

So I think Scala cannot choose between the class-scope implicit and method-scope implicit.

2
There is no way to "change" the resolution rules for implicit scope. Have to cope with it.cchantep

2 Answers

7
votes

In dotty/scala 3 that should already work as you intended (second bullet point). In Scala 2 you have to shadow the implicit in the outer scope by giving them the same name.

object Foo {
  implicit val a: Int = 1
  def bar: Int = {
    implicit val a: Int = 2
    implicitly[Int] // 2
  }
}

That's the strategy that was used in the implementation of the Scala 3 compiler, when it was compiled with Scala 2: http://dotty.epfl.ch/docs/internals/contexts.html#using-contexts

2
votes

You can`t do this in the current Scala 2. At least without unclear approaches (hacks) like shadowing.

Because there is no difference between method scope or class member scope or code block scope. You have only two scopes - the local scope and the scope of corresponding types. You can read about there (Implicit Scope and Implicit Resolution).

What you can do to achieve wanted results?

You can move your code into another scope. E.g. a newly created static object.

object Foo {
  implicit val a: Int = 1
  val b: Int = 2
  def bar: Int = AnotherScopeObject.bar(b)
}

object AnotherScopeObject {
  def bar(implicit implicitInt: Int) : Int = {
    implicitly[Int]
  }
}