Как предпочесть неявную область видимости метода над областью класса? - PullRequest
1 голос
/ 06 августа 2020

У меня есть код Scala, аналогичный приведенному ниже. Существует неявное определение на уровне класса / объекта, и я хочу «переопределить» его неявным определением в методе. (Если вам действительно нужно знать, мне нужно изменить свой ExecutionContext специально для рассматриваемого метода).

В этом примере я хочу использовать b как неявное для Int в объем метода bar. Как я могу это сделать?

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

Это жалуется на

error: неоднозначные неявные значения: оба значения a в объекте Foo типа Int и значение b типа Int соответствуют ожидаемому type Int

Поэтому я думаю, что Scala не может выбирать между неявной областью класса и неявной областью метода.

Ответы [ 2 ]

6 голосов
/ 06 августа 2020

В dotty / scala 3 это уже должно работать так, как вы предполагали ( вторая точка маркера ). В Scala 2 вы должны затенять неявное во внешней области видимости, давая им одно и то же имя.

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

Это стратегия, которая использовалась в реализации компилятора Scala 3, когда он был скомпилирован с Scala 2: http://dotty.epfl.ch/docs/internals/contexts.html#using -контекстами

2 голосов
/ 06 августа 2020

Вы не можете сделать это в текущем Scala 2. По крайней мере, без неясных подходов (хаков), таких как затенение.

Потому что нет разницы между областью действия метода, областью члена класса или областью блока кода . У вас есть только две области видимости - локальная область и область действия соответствующих типов. Здесь вы можете прочитать про (Implicit Scope and Implicit Resolution) .

Что вы можете сделать для достижения желаемых результатов?

Вы можете переместить свой код в другую область. Например, недавно созданный объект stati c.

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]
  }
}
...