Scala 3 for推导式中获取参数化类型隐式值的语法问题
Scala 3 for推导式内隐式值查找失效问题说明
问题本质
首先纠正认知偏差:这个问题和隐式值是否为参数化类型完全无关,你给出的首个示例中非参数化的Int类型隐式值同样会触发查找失败,本质是Scala 3 for推导式的隐式作用域划分规则导致的。
Scala 3的for推导式会以带<-的生成器语句为边界划分独立的隐式作用域段:
- 同一个作用域段内,生成器之后直接通过
given定义的隐式值,不会被同段内后续通过=定义的赋值语句的隐式解析逻辑识别 - 只有当新的生成器语句出现、开启下一个作用域段后,之前段内定义的所有
given才会被纳入新段的隐式上下文,可被后续语句正常查找
这就是为什么插入dummy生成器后隐式查找恢复正常的原因,和类型本身的参数化属性没有关联。
可行解决方式
- 轻量切割作用域:在
given定义和隐式查找语句之间插入一个无业务逻辑的纯生成器即可,不需要构造多余的dummy值,推荐用_ <- Some(()),无额外运行时开销:
for o <- Option("line just to make for comprehension start") given Int = 2 given List[Int] = List(1, 2, 3) _ <- Some(()) a = implicitly[Int] // 正常编译 b = implicitly[List[Int]] // 正常编译 yield ()
- 将隐式查找逻辑移到
yield块内:yield块可以正常识别for推导式内之前定义的所有given值,不需要额外插入生成器:
for o <- Option("line just to make for comprehension start") given Int = 2 given List[Int] = List(1, 2, 3) yield val a = implicitly[Int] // 正常编译 val b = implicitly[List[Int]] // 正常编译 ()
- 将公共隐式值定义挪到for推导式外部:如果隐式值不需要依赖for内之前生成的变量,直接定义在for外部即可全局被识别。
内容的提问来源于stack exchange,提问作者Hunor Kovács
相关产品推荐
相关产品推荐

