我注意到以下两个for循环案例有时表现不同,而大多数时候它们是相同的。我无法弄清楚这种模式,有没有人有任何想法?谢谢!
案例1:
for (i <- myList.length - 1 to 0 by -1) { ... }
案例2:
for (i <- myList.length - 1 to 0) { ...}
答案 0 :(得分:0)
n to 0 by -1
表示“从n
开始,然后转到0,将向后计算增加1.所以:
5 to 0 by -1
// res0: scala.collection.immutable.Range = Range(5, 4, 3, 2, 1, 0)
而n to 0
的意思是“从n
开始,到0计算前进 1”。但你会注意到,如果n > 0
,则该列表中没有任何内容,因为无法从大于零的任何内容将前进计为0。
5 to 0
// res1: scala.collection.immutable.Range.Inclusive = Range()
它们产生相同结果的唯一方法是n=0
,因为从0到0的计数是向前和向后相同的:
0 to 0 by -1 // Range(0)
0 to 0 // Range(0)
在您的情况下,由于您从myList.length - 1
开始,当myList
的长度为1时,它们将产生相同的结果。
总之,第一个版本是有意义的,因为你想通过向后计数(by -1
)倒数到0。而第二个版本没有意义,因为你不想将前进从一个长度计算为0(这必然是非负的)。
答案 1 :(得分:0)
首先,我们需要详细了解价值成员to
和by
的工作原理。
to
- 点击Here获取API文档
to
是一个值成员,出现在int,double等类中。
scala> 1 to 3
res35: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3)
老实说,你不必使用start to end by step
并且如果你在这个世界上更适合工作,那么start.to(end,step)也会有效。基本上,如果我们讨论整数输入,to
将返回一个Range.Inclusive对象。
by
- 点击Here获取API文档
使用此范围的起始值和结束值以及新步骤
创建新范围
scala> Range(1,8) by 3
res54: scala.collection.immutable.Range = Range(1, 4, 7)
scala> Range(1,8).by(3)
res55: scala.collection.immutable.Range = Range(1, 4, 7)
最后,让我们花一些时间来看看当步骤从开始到结束的不同方向时会发生什么。与1 to 3 by -1
以下是Range类的源代码,实际上非常简单易读:
def by(step: Int): Range = copy(start, end, step)
所以by
实际上正在调用函数copy
,那么复制是什么?
protected def copy(start: Int, end: Int, step: Int): Range = new Range(start, end, step)
所以copy
从字面上重新创建一个具有不同步骤的新范围,然后让我们看一下构造函数或Range本身。
阅读本段代码
override final val isEmpty = (
(start > end && step > 0)
|| (start < end && step < 0)
|| (start == end && !isInclusive)
)
这些情况会触发异常,在1 to 3 by -1
等情况下,您的结果将为空范围。
抱歉我的帖子已经失控,因为我现在也在学习Scala 为什么不阅读Range的源代码,它是由Martin Odersky编写的,只有500行,包括评论:)