依名稱上下文參數
可以宣告依名稱內容參數,以避免發散的推論擴充。範例
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
的新 givengiven lv: T = ???
其中
lv
是任意的新名稱。 -
此 given 並未立即可用作引數推論的候選項(使其立即可用會導致合成運算中出現迴圈)。但它會在所有再次尋找依名稱內容參數引數的巢狀內容中可用。
-
如果此搜尋使用表達式
E
成功,且E
包含對lv
的參照,請將E
替換為{ given lv: T = E; lv }
否則,不變更傳回
E
。
在上述範例中,s
的定義會擴充為如下。
val s = summon[Test.Codec[Option[Int]]](
using optionCodec[Int](using intCodec)
)
未產生任何區域提供實例,因為合成引數並非遞迴。
參考
如需更多資訊,請參閱 Issue #1998 和相關的 Scala SIP。
本文內容