在Scala中,带有多个生成器的for循环是如何工作的?

10 浏览
0 Comments

在Scala中,带有多个生成器的for循环是如何工作的?

我对Scala还不熟悉,但我希望从函数式的角度理解它。对于以下代码片段的行为,我感到非常困惑。

val res = for {
  i <- 1 to 2
  j <- 1 to 2
} yield (i, j)
println(s"res is $res")

这段代码会按预期输出res is Vector((1,1), (1,2), (2,1), (2,2))。然而,稍微修改一下上面的代码:

val res = for {
  i <- 1 to 2
  j <- i to 0
} yield (i, j)
println(s"res is $res")

输出结果为res is Vector()。为什么第二个循环版本没有生成Vector((1,1), (1,0), (2,2), (2,1), (2,0))呢?

这种行为对我在Scala中使用索引循环遍历2D矩阵的能力有重要影响。一般来说,有什么方法可以在保持跟踪行和列索引的情况下,以惯用方式循环遍历矩阵的上三角部分?

0
0 Comments

在Scala中,使用多个生成器的for循环是如何工作的呢?我们可以通过REPL来了解。

在REPL中,输入1 to 2,会返回res0: scala.collection.immutable.Range.Inclusive = Range 1 to 2,表示生成了一个从1到2的范围。而输入1 to 0,会返回res1: scala.collection.immutable.Range.Inclusive = empty Range 1 to 0,表示生成了一个空的范围,这是因为范围默认是向上递增的。

那么如果我们想要实现向下递减的范围呢?可以通过在生成器中指定递减的步长来实现。如下代码所示:

val res = for {
  i <- 1 to 2
  j <- i to 0 by -1
} yield (i, j)
//res: IndexedSeq[(Int, Int)] = Vector((1,1), (1,0), (2,2), (2,1), (2,0))

上面的代码中,我们使用两个生成器,第一个生成器生成了从1到2的范围,第二个生成器生成了从i到0的范围,且步长为-1,即递减。最后使用yield关键字将结果存储在一个IndexedSeq中。

需要注意的是,当使用递减步长时,范围的起始值必须大于等于结束值,否则将得到一个空的范围。

如果你需要更多关于范围的信息,可以参考以下链接:stackoverflow.com/questions/2617513/...

如果你想了解上三角循环的惯用法,可以参考以下链接:stackoverflow.com/questions/18707121/...

0