按名称上下文参数
可以按名称声明上下文参数,以避免发散的推断展开。示例
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)
)
未生成局部给定实例,因为合成参数不是递归的。
参考
本文中