2012-05-09 96 views
3

我是新來的Scala語言。scala範圍長

我需要範圍爲長類型。

我需要步驟1的[1,2,3 ... 10000000]的列表。如果我使用直到/因爲使用Long而不是Int得到錯誤。

我嘗試編寫一個簡單的函數,它需要一個開始,結束和一個空列表並生成[start .. end]列表。

這裏是我的功能:

def range_l(start : Long, end : Long, list : List[Long]) : List[Long] = { 
    if (start == end){ 
     val add_to_list = start :: list 
     return add_to_list 
    } 
    else { 
     val add_to_list = start :: list 
     range_l(start + 1, end, add_to_list) 
    } 
} 

如果我這樣稱呼它:range_l(1L, 1000000L, List())我在下面的行獲得OutOfMemory錯誤:add_to_list = start :: list

你能指點我?我如何獲得Range[Long]或如何優化功能。我如何避免OutOfMemory?

謝謝。

+2

範圍一般不需要實現。在REPL上嘗試'1.to(Int.MaxValue)'並查看結果類型。請隨時[查看Scala源代碼](http://www.scala-lang.org/api/current/scala/collection/immutable/Range$$Inclusive.html)查找此類型:) – 2012-05-09 07:00:03

+2

您正在談論關於'Range',但是你的函數返回'List',它是scala中的不同類型。如果你想'List [Long]',你可以'List.range(0L,10)' – 4e6

+1

爲什麼你需要這樣一個範圍?獲得一個很容易(見範式的答案),但使用它往往是不切實際的。您的問題可能會有更好的解決方案。另外,你的錯誤是什麼? '1到10000000'不會給出錯誤。 –

回答

5

你可能不需要一個範圍。我會帶一個Stream並迭代它。

def stream(i: Long = 1): Stream[Long] = i #:: stream(i + 1) 

產生流無界其中元素之間的差異是1。因爲流是延遲集合就不會GETT任何錯誤。遍歷千萬元,你只需使用以下命令:

val range = stream take 10000000 
for (i <- range) { 
    ... 
} 

take 10000000將返回Stream大小爲10000000。因爲StreamIterable你可以把它傳遞給了comprehansion。

7

您可以通過使用以下語法創建這樣一個範圍:

val range = 1L to 10000000L 

的「L」是必須告知編譯器的litterals是多頭,而不是整數。

然後,您可以使用實例range上的幾乎所有List方法。它不應該填滿你的記憶,因爲中間值是在需要時生成的。該範圍可以傳遞給期待Traversable[Long],一個Seq[Long],一個Iterable[Long]任何方法等

但是,如果你真的需要一個List只需調用range.toList(和增加堆大小,以適應所有的列表元素)..

+2

雖然'1L到10000000000L'產生IllegalArgumentException:「seqs不能包含多於Int.MaxValue元素」 – DNA

+0

@DNA確實,在這種情況下,您可以使用流或您自己的迭代器。標準庫集合有一個size方法,它必須返回一個Int ...如果你有特殊需求,你應該使用一個特殊的集合。 – paradigmatic