你可以完成大部分的你會用Ruby想要的東西或C#的yield
使用Stream
:
def splitOnBlankLines(iter: Iterator[String]): Iterator[Seq[String]] = {
def asStream(list: List[String]): Stream[List[String]] = {
if (iter.hasNext) {
val line = iter.next()
if (line == "")
list.reverse #:: asStream(Nil)
else
asStream(line :: list)
} else {
list.reverse #:: Stream.empty
}
}
asStream(Nil).iterator
}
每當我們會想yield
,我們使用#::
與價值,我們希望在這種情況下返回(list.reverse
)和表示流的其餘部分的表達式。 #::
將此表達式作爲一個名稱參數,所以它不會執行,直到需要其餘的Stream
。當返回最後一個值時,我們使用Stream.empty
來表示不會生成更多值。
這是可能的的Stream
這種行爲結合與延續插件得到的東西語法上等同於Ruby或的yield
(在所有二十行代碼)C#,但延續插件是不可能永遠成爲穩定。
然而,手工編寫的Iterator
幾乎是一樣簡單:
import scala.annotation.tailrec
class BlankLineSplittingIterator(iter: Iterator[String]) extends Iterator[Seq[String]] {
def hasNext = iter.hasNext
def next = {
if (!iter.hasNext)
Iterator.empty.next
@tailrec def untilBlank(list: List[String]): List[String] = {
val line = iter.next()
if (line == "" || !iter.hasNext)
list.reverse
else
untilBlank(line :: list)
}
untilBlank(Nil)
}
}
爲什麼你想要這些特定類型?爲什麼不'Seq [Seq [String]]'? – Bill
我不想一次把所有內容都放在內存中。 – schmmd
我知道你說過「沒有迭代」,但是考慮給[Scalaz Stream](https://github.com/scalaz/scalaz-stream)一試!它沒有比'io.linesR(「data.txt」)更好。split(_。isEmpty)'。 –