Abh*_*kar 7 scala stream lazy-evaluation
在Scala中,有没有办法在Stream中获取当前评估的项目?例如在Stream中
val s: Stream[Int] = Stream.cons(1, Stream.cons(2, Stream.cons(3, s.map(_+1))))
Run Code Online (Sandbox Code Playgroud)
该方法应该只返回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
}
}
Run Code Online (Sandbox Code Playgroud)
在这里你可以看到它的实际效果:
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
Run Code Online (Sandbox Code Playgroud)
基于Rex答案的解决方案:
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())
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
434 次 |
最近记录: |