按名称上下文参数
可以按名称声明上下文参数,以避免发散的推断展开。示例
trait Codec[T]:
def write(x: T): Unit
given intCodec: Codec[Int] = ???
given optionCodec[T](using ev: => Codec[T]): Codec[Option[T]] with
def write(xo: Option[T]) = xo match
case Some(x) => ev.write(x)
case None =>
val s = summon[Codec[Option[Int]]]
s.write(Some(33))
s.write(None)
与普通按名称参数的情况一样,上下文参数 ev 的参数按需求值。在上面的示例中,如果选项值 x 为 None,则根本不会对其进行求值。
如果需要防止其他发散的展开,则按名称上下文参数的合成参数将由本地 val 支持。
为类型为 => T 的按名称上下文参数合成参数的精确步骤如下。
-
创建类型为
T的新给定given lv: T = ???其中
lv是任意新名称。 -
此给定不会立即作为参数推断的候选(立即使其可用可能会导致合成计算出现循环)。但在所有嵌套上下文中,它会再次查找按名称上下文参数的参数时可用。
-
如果此搜索使用表达式
E成功,且E包含对lv的引用,则用以下内容替换E{ given lv: T = E; lv }否则,返回未更改的
E。
在上面的示例中,s 的定义将扩展如下。
val s = summon[Test.Codec[Option[Int]]](
using optionCodec[Int](using intCodec)
)
未生成局部给定实例,因为合成参数不是递归的。
参考
本文中