用于Scala中的理解评估的奇怪(?)

Mic*_*Rus 4 recursion scala for-comprehension

现在,我花了一段时间才弄明白为什么我的递归以某种方式成功地炸毁堆栈.这就是导致这个问题的部分:

scala> for {
     |   i <- List(1, 2, 3)
     |   j = { println("why am I evaluated?"); 10 } if false
     | } yield (i, j)
why am I evaluated?
why am I evaluated?
why am I evaluated?
res0: List[(Int, Int)] = List()
Run Code Online (Sandbox Code Playgroud)

这不是疯了吗?为什么要评估j = ...它是否结束if false,因此永远不会被使用?

我学到了什么,而不是{ println ... }你有一个递归调用(和递归防护而不是if false),会发生什么.<

为什么?!

som*_*ytt 7

我打算走出去,说接受的答案可以说更多.

这是一个解析器错误.

警卫可以立即跟随发电机,但是否则semi需要(实际或推断).

这是语法.

在下面,该行res4不应该编译.

scala> for (i <- (1 to 5).toList ; j = 2 * i if j > 4) yield j
res4: List[Int] = List(6, 8, 10)

scala> for (i <- (1 to 5).toList ; j = 2 * i ; if j > 4) yield j
res5: List[Int] = List(6, 8, 10)
Run Code Online (Sandbox Code Playgroud)

会发生什么是j的val def与i生成器合并以生成新的生成器对(i,j).然后警卫看起来就像跟随(合成)发电机一样.

但语法仍然是错误的.语法是我们的​​朋友!在类型系统之前很久就是我们的BFF.

在线上res5,很明显,后卫没有防守val def.

更新:

实施错误被降级(或升级,取决于您的观点)到规范错误.

检查这种用法,如果控制前面的valdef,就像在Perl中一样,后卫看起来像尾随,属于你最喜欢的样式检查器的范围.