Scala 2.12.4(Scastie环境)使用中间变量时for推导式失败
解决Scala 2.12.4中For推导式中间变量报错问题
我先还原你大概率遇到的报错场景,比如你可能写了类似这样的代码:
val nums = List(1, 2, 3) // 报错的for推导式 val faultyResult = for { square = n * n // XXX 这行触发报错:not found: value n n <- nums } yield square
报错原因
Scala的for推导式是严格按照从上到下的顺序解析的:生成器(<-语法)负责引入新的变量,而中间变量(=语法)只能依赖于之前已经定义好的变量(包括前面生成器引入的变量,或者外部作用域的变量)。
在上面的错误代码里,square = n * n写在了n <- nums之前,此时n还没被生成器引入,编译器找不到这个变量,自然就抛出了not found: value n的错误。
正确的写法
只需要调整代码顺序,把生成器放在中间变量的前面,确保中间变量使用的变量已经被定义:
val nums = List(1, 2, 3) // 正常运行的for推导式 val correctResult = for { n <- nums square = n * n // 现在n已经被前面的生成器引入,可以正常使用 } yield square // 输出结果:List(1, 4, 9)
另一种常见错误场景:混淆中间变量与生成器
还有一种可能是,你想把返回集合/Monad的表达式作为中间步骤,但错误地用了=而非<-,比如:
val nums = List(1, 2, 3) // 不符合预期的代码(不一定报错,但结果不是你想要的) val faultyResult2 = for { n <- nums // XXX 这里如果想展开List,用=会导致嵌套集合,而非扁平化结果 squares = List(n*n, n*n*n) } yield squares // 结果是:List(List(1,1), List(4,8), List(9,27))
如果你的目标是扁平化这个集合,应该用<-(这会触发flatMap操作):
val nums = List(1, 2, 3) val correctResult2 = for { n <- nums square <- List(n*n, n*n*n) } yield square // 输出结果:List(1, 1, 4, 8, 9, 27)
总结
- For推导式中,生成器(
<-)必须在依赖它的中间变量(=)之前,确保变量先被引入再使用。 - 明确区分中间变量(
=,用于计算临时值,不会展开Monad/集合)和生成器(<-,用于展开Monad/集合,触发flatMap操作)。
内容的提问来源于stack exchange,提问作者0__
相关产品推荐
相关产品推荐

