scala - 在 Scala 中用于理解性评估的奇怪 (?)

标签 scala recursion 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()

这不是很疯狂吗?为什么要评价j = ...如果它以 if false 结尾等会从不 使用?

代替 { println ... } 时会发生什么你有一个递归调用(和递归保护而不是 if false ),我知道。 :<

为什么?!

最佳答案

我要出去说接受的答案可以说更多。

这是一个解析器错误。

守卫可以立即跟随一个生成器,否则是 semi是必需的(实际的或推断的)。

Here is the syntax.

下面是 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)

发生的情况是 j 的 val def 与 i 生成器合并以形成一个新的生成器对 (i,j) .然后守卫看起来就像它只是跟随(合成)生成器。

但是语法仍然是错误的。语法是我们的​​ friend !早在类型系统出现之前,它就是我们的 BFF。

在线咨询 res5 ,很明显,后卫没有保护 val def。

更新:

实现错误已降级(或升级,取决于您的观点)为 specification bug .

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

关于scala - 在 Scala 中用于理解性评估的奇怪 (?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19599947/

相关文章:

scala - 根据验证是成功还是失败执行不同副作用的最佳方式

python - 我如何错误地使用 copytree 以及如何修复它以免陷入巨大的循环?

scala - 为什么Scala为涉及Either和值定义的 'Product'表达式选择类型 'for'

scala - 在 Scala 中使用 for-comprehension、Try 和序列

scala - for..else用于Scala中的Option类型?

scala - action和action.async之间的区别

Scala酸洗和类型参数

python - 在这个硬币找零问题中,我该如何做 "recursive"for 循环?

scala - 递归值 xxx 需要在 Scala 中输入

Python递归查找文件并移动到一个目标目录