在斯卡拉,有沒有一種方法來獲取流中當前評估的項目?例如在流中在斯卡拉,有沒有一種方法來獲取流中當前評估的項目?
val s: Stream[Int] = Stream.cons(1, Stream.cons(2, Stream.cons(3, s.map(_+1))))
該方法應該只返回List(1,2,3)
。
在斯卡拉,有沒有一種方法來獲取流中當前評估的項目?例如在流中在斯卡拉,有沒有一種方法來獲取流中當前評估的項目?
val s: Stream[Int] = Stream.cons(1, Stream.cons(2, Stream.cons(3, s.map(_+1))))
該方法應該只返回List(1,2,3)
。
2.8中有一個被保護的方法tailDefined
,當你到達尚未評估過的流中的點時,它將返回false。
這不是太有用(除非你想寫自己的Stream
類),但Cons
本身使該方法公開。我不確定它爲什麼在Stream中受到保護,而不在Cons中 - 我認爲其中一個可能是一個bug。但現在,至少,你可以寫像這樣的方法(在刻錄功能等同物作爲練習留給讀者):
def streamEvalLen[T](s: Stream[T]) = {
if (s.isEmpty) 0
else {
var i = 1
var t = s
while (t match {
case c: Stream.Cons[_] => c.tailDefined
case _ => false
}) {
i += 1
t = t.tail
}
i
}
}
在這裏,你可以看到它在行動:
scala> val s = Stream.iterate(0)(_+1)
s: scala.collection.immutable.Stream[Int] = Stream(0, ?)
scala> streamEvalLen(s)
res0: Int = 1
scala> s.take(3).toList
res1: List[Int] = List(0, 1, 2)
scala> s
res2: scala.collection.immutable.Stream[Int] = Stream(0, 1, 2, ?)
scala> streamEvalLen(s)
res3: Int = 3
將該語句鍵入到交互式shell中,您將看到它的計算結果爲s: Stream[Int] = Stream(1, ?)
。所以,事實上,2和3的其他兩個元素還不知道。
當您訪問更多元素時,會計算更多的流。所以,現在將s(3)
放入shell中,這將返回res0: Int = 2
。現在將s
放入shell中,您將看到新值res1: Stream[Int] = Stream(1, 2, 3, 2, ?)
。
不幸的是,我能找到的唯一一種包含所需信息的方法是s.toString
。通過一些解析,您將能夠將元素從字符串中取出。這僅僅是一個幾乎不可接受的解決方案,我無法想象任何使用字符串解析思想的通用解決方案。
基於Rex's answer解決辦法:
def evaluatedItems[T](stream: => Stream[T]): List[T] = {
@tailrec
def inner(s: => Stream[T], acc: List[T]): List[T] = s match {
case Empty => acc
case c: Cons[T] => if (c.tailDefined) {
inner(c.tail, acC++ List(c.head))
} else { acC++ List(c.head) }
}
inner(stream, List())
}
使用scanLeft
lazy val s: Stream[Int] = 1 #:: s.scanLeft(2) { case (a, _) => 1 + a }
'tailDefined'方法在'Cons'和'Empty'中都是公共的,所以我不認爲它是一個錯誤。我以前沒注意到。我可以調整你的解決方案來解決我的問題。 – 2010-05-14 20:42:43