Предположим, что мы имеем неявный поиск параметров, относящийся только к локальным областям:
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)
}
В приведенном выше коде LocalIntFoo
побеждает над ImportedIntFoo
.
Может ли кто-нибудь объяснить, как он более конкретно рассматривается, используя "правила статического перегрузочного разрешения (§6.26.3)"?
Edit
Приоритет привязки имени является убедительным аргументом, но есть несколько нерешенных проблем. Во-первых, Scala Справочник по языку говорит:
Если имеется несколько подходящих аргументов, которые соответствуют типу неявных параметров, наиболее конкретный будет выбран с использованием правил статического перегрузочного разрешения (§6.26.3).
Во-вторых, приоритет привязки имени заключается в разрешении известного идентификатора x
на конкретный элемент pkg.A.B.x
в случае, если в области видится несколько переменных/методов/объектов с именем x
. ImportIntFoo
и LocalIntFoo
не называются одинаковыми.
В-третьих, я могу показать, что приоритет привязки имени не входит в игру следующим образом:
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 LocalAnyFoo extends CanFoo[Any] {
def foos(x: Any) = "LocalAnyFoo:" + x.toString
}
// 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)
Поместите это в test.scala
и запустите scala test.scala
, и он выведет ImportIntFoo:1
.
Это связано с тем, что статическое перегрузочное разрешение (§6.26.3) говорит о более конкретных типах выигрышей.
Если мы притворяемся, что все подходящие неявные значения называются одинаковыми, LocalAnyFoo
должен быть замаскирован ImportIntFoo
.
Похожие
Это отличное резюме неявного разрешения параметров, но оно цитирует презентацию Josh nescala вместо спецификации. Его разговор побудил меня взглянуть на это.
Внедрение компилятора