2011-09-08 78 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) 
} 

獺指出,「到」包括右端點「,直到」省略「。