在Scala中,有没有一种方法可以获取流中当前评估的项?

在Scala中,有没有一种方法可以获取流中当前评估的项?,scala,stream,lazy-evaluation,Scala,Stream,Lazy Evaluation,在Scala中,有没有一种方法可以获取流中当前评估的项?例如在流中 val s: Stream[Int] = Stream.cons(1, Stream.cons(2, Stream.cons(3, s.map(_+1)))) 该方法应该只返回List(1,2,3)在交互式shell中键入该语句,您将看到它的计算结果为s:Stream[Int]=Stream(1,?)。所以,事实上,2和3的另外两个元素还不知道 当您访问更多的元素时,将计算更多的流。因此,现在将s(3)放入shell,它将返回

在Scala中,有没有一种方法可以获取流中当前评估的项?例如在流中

val s: Stream[Int] = Stream.cons(1, Stream.cons(2, Stream.cons(3, s.map(_+1))))

该方法应该只返回
List(1,2,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
。通过一些解析,您将能够从字符串中获取元素。这是一个仅包含int的勉强可接受的解决方案,我无法想象任何使用字符串解析思想的通用解决方案。

在2.8中,有一个名为
tailDefined
的受保护方法,当到达流中尚未计算的点时,该方法将返回false

这不是很有用(除非您想编写自己的
Stream
类),除非
Cons
本身将方法公开。我不知道为什么它在流中而不是在Cons中受到保护——我认为其中一个可能是一个bug。但现在,至少您可以编写这样的方法(编写函数等价物作为练习留给读者):

在这里,您可以看到它的作用:

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
解决方案基于:

使用scanLeft

    lazy val s: Stream[Int] = 1 #:: s.scanLeft(2) { case (a, _) => 1 + a }

方法
tailDefined
Cons
Empty
中都是公共的,所以我不认为这是一个bug。我之前没有注意到。我可以调整你的解决方案来解决我的问题。
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())
}
    lazy val s: Stream[Int] = 1 #:: s.scanLeft(2) { case (a, _) => 1 + a }