在 GitHub 上编辑此页面

按名称上下文参数

可以按名称声明上下文参数,以避免发散的推断展开。示例

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 的参数按需求值。在上面的示例中,如果选项值 xNone,则根本不会对其进行求值。

如果需要防止其他发散的展开,则按名称上下文参数的合成参数将由本地 val 支持。

为类型为 => T 的按名称上下文参数合成参数的精确步骤如下。

  1. 创建类型为 T 的新给定

    given lv: T = ???
    

    其中 lv 是任意新名称。

  2. 此给定不会立即作为参数推断的候选(立即使其可用可能会导致合成计算出现循环)。但在所有嵌套上下文中,它会再次查找按名称上下文参数的参数时可用。

  3. 如果此搜索使用表达式 E 成功,且 E 包含对 lv 的引用,则用以下内容替换 E

    { given lv: T = E; lv }
    

    否则,返回未更改的 E

在上面的示例中,s 的定义将扩展如下。

val s = summon[Test.Codec[Option[Int]]](
  using optionCodec[Int](using intCodec)
)

未生成局部给定实例,因为合成参数不是递归的。

参考

有关详细信息,请参阅 问题 #1998 和关联的 Scala SIP

本文中