请考虑io
软件包中提供的默认编解码器。
implicitly[io.Codec].name //res0: String = UTF-8
这是隐式的“低优先级”,因此很容易将其覆盖而不会产生歧义。
implicit val betterCodec: io.Codec = io.Codec("US-ASCII")
implicitly[io.Codec].name //res1: String = US-ASCII
提高优先级也很容易。
import io.Codec.fallbackSystemCodec
implicit val betterCodec: io.Codec = io.Codec("US-ASCII")
implicitly[io.Codec].name //won't compile: ambiguous implicit values
但是我们可以朝相反的方向走吗?我们可以创建一个低级别的隐式来禁用(“歧义化”)默认值吗?我一直在研究优先级方程式,并使用低优先级隐式变量进行操作,但尚未创建与默认值不明确的内容。
答案 0 :(得分:1)
如果我正确理解,则想在编译时检查是否存在局部隐式io.Codec
(“高优先级”),否则会产生编译错误。可以使用宏(使用编译器内部函数)完成此操作。
import scala.language.experimental.macros
import scala.reflect.macros.{contexts, whitebox}
object Macros {
def localImplicitly[A]: A = macro impl[A]
def impl[A: c.WeakTypeTag](c: whitebox.Context): c.Tree = {
import c.universe._
val context = c.asInstanceOf[contexts.Context]
val global: context.universe.type = context.universe
val analyzer: global.analyzer.type = global.analyzer
val callsiteContext = context.callsiteTyper.context
val tpA = weakTypeOf[A]
val localImplicit = new analyzer.ImplicitSearch(
tree = EmptyTree.asInstanceOf[global.Tree],
pt = tpA.asInstanceOf[global.Type],
isView = false,
context0 = callsiteContext.makeImplicit(reportAmbiguousErrors = true),
pos0 = c.enclosingPosition.asInstanceOf[global.Position]
) {
override def searchImplicit(
implicitInfoss: List[List[analyzer.ImplicitInfo]],
isLocalToCallsite: Boolean
): analyzer.SearchResult = {
if (isLocalToCallsite)
super.searchImplicit(implicitInfoss, isLocalToCallsite)
else analyzer.SearchFailure
}
}.bestImplicit
if (localImplicit.isSuccess)
localImplicit.tree.asInstanceOf[c.Tree]
else c.abort(c.enclosingPosition, s"no local implicit $tpA")
}
}
localImplicitly[io.Codec].name // doesn't compile
// Error: no local implicit scala.io.Codec
implicit val betterCodec: io.Codec = io.Codec("US-ASCII")
localImplicitly[Codec].name // US-ASCII
import io.Codec.fallbackSystemCodec
localImplicitly[Codec].name // UTF-8
import io.Codec.fallbackSystemCodec
implicit val betterCodec: io.Codec = io.Codec("US-ASCII")
localImplicitly[Codec].name // doesn't compile
//Error: ambiguous implicit values:
// both value betterCodec in object App of type => scala.io.Codec
// and lazy value fallbackSystemCodec in trait LowPriorityCodecImplicits of type => //scala.io.Codec
// match expected type scala.io.Codec
在2.13.0中进行了测试。
libraryDependencies ++= Seq(
scalaOrganization.value % "scala-reflect" % scalaVersion.value,
scalaOrganization.value % "scala-compiler" % scalaVersion.value
)
答案 1 :(得分:-1)
是的,是的。
您可以通过创建“新类型”来实现。即一种类型,它只是io.Codec
的代理,并包装实例。这意味着您还需要将所有隐式参数从io.Codec
更改为CodecWrapper
,这可能是不可能的。
trait CodecWraper {
def orphan: io.Codec
}
object CodecWrapper {
/* because it's in the companion, this will have the highest implicit resolution priority. */
implicit def defaultInstance: CodecWrapper =
new CodecWrapper {
def orphan = new io.Codec { /* your default implementation here */ }
}
}
}
import io.Codec.fallbackSystemCodec
implicitly[CodecWrapper].orphan // io.Codec we defined above - no ambiguity