2011-09-08 50 views
9

因此,当我通过“Scala for the Impatient”工作时,我发现自己想知道:如果没有序列,您可以使用Scala for循环吗?For循环scala没有序列?

例如,本书中有一项练习要求您构建一个无法在Integer.MAX_VALUE之前递增的计数器对象。为了测试我的解决方案,我写了下面的代码:

var c = new Counter 
for(i <- 0 to Integer.MAX_VALUE) c.increment() 

这将引发一个错误:序列不能包含Int.MaxValue元素更多。 在我看来,这意味着Scala首先分配并填充序列对象,值为0到Integer.MaxValue,然后对该序列对象执行foreach循环。

我知道我能做到这一点,而不是:

var c = new Counter 
while(c.value < Integer.MAX_VALUE) c.increment() 

但有没有办法做一个传统的C风格的for循环与for语句?

回答

17

事实上,0 to N实际上不填充整数从东西向0N。它会创建一个scala.collection.immutable.Range的实例,该实例将其方法应用于动态生成的所有整数。

您遇到的错误仅仅是因为您必须能够将Int的正数部分(无论它们实际存在与否)纳入其正数部分,以便维护length方法的合同。 1 to Int.MaxValue正常工作,因为0 until Int.MaxValue。而后者就是你的while循环所做的(to包含正确的端点,until省略了它)。

无论如何,因为斯卡拉for是一个非常不同的(更通用)的生物比C for,简单的答案是否定的,你不能做同样的事情。但是你可以用for做你想做的事(尽管可能不如你想的那么快,因为有一些性能损失)。

4

是和否,这取决于您要求的内容。如果你问你是否可以通过整数序列重复,而不必首先建立一个序列,然后是你可以,例如使用流:

def fromTo(from : Int, to : Int) : Stream[Int] = 
    if(from > to) { 
    Stream.empty 
    } else { 
    // println("one more.") // uncomment to see when it is called 
    Stream.cons(from, fromTo(from + 1, to)) 
    } 

然后:

for(i <- fromTo(0, 5)) println(i) 

编写您自定义hasNext和next是另一种选择。

如果你问是否可以使用'for'语法来编写一个“本地”循环,即循环通过增加一些本地整数来工作,而不是迭代对象实例产生的值,那么就我所知,答案是不。正如你可能知道的,'for'理解是句法糖,用于调用flatMap,filter,map和/或foreach(全部在FilterMonadic特性中定义)的组合,具体取决于生成器及其类型的嵌套。您可以尝试编译一些循环并打印其编译器中间表示形式,其中包含

scalac -Xprint:refchecks 

以查看它们是如何扩展的。

+0

哇,一个具有挑战性的答案,但一个很好的答案。我只是在学习Scala,所以你用了很多我只是不太熟悉的术语,但是谢谢。 –

+0

'fromTo'的定义可以通过在'Stream'(或'Iterator')伴随对象上使用'iterate'方法进一步简化。 (def fromTo(from:Int,to:Int)= Stream.iterate(from,to - from)(_ + 1)')。但是使用'from to to'更加习惯并且达到同样的效果。 –

2

这里有一堆这些,但我不能困扰他们目前搜索。以下是相当典型:

@scala.annotation.tailrec 
def loop(from: Int, until: Int)(f: Int => Unit): Unit = { 
    if (from < until) { 
    f(from) 
    loop(from + 1, until)(f) 
    } 
} 

loop(0, 10) { i => 
    println("Hi " + i) 
} 
5

哇,一个简单的问题,一些不错的技术解答(这是很好的!),但如果有些人只是为了寻找一个简单的答案:

//start from 0, stop at 9 inclusive 
for (i <- 0 until 10){ 
    println("Hi " + i) 
} 

//or start from 0, stop at 9 inclusive 
for (i <- 0 to 9){ 
    println("Hi " + i) 
} 

獭指出,“到”包括右端点“,直到”省略“。