В Scala, там способ получить в настоящее время оцениваемые объекты в Потоке? Например, в Потоке
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 - я бы подумал, что одно или другое может быть ошибкой. Но пока, по крайней мере, вы можете написать такой метод (написание функционального эквивалента остается для читателя в качестве упражнения):
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
Решение, основанное на ответе Рекса :
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())
}
Введите этот оператор в интерактивную оболочку, и вы увидите, что он оценивается как s: Stream [Int] = Stream (1,?)
. Фактически, два других элемента 2 и 3 еще не известны.
По мере доступа к дополнительным элементам вычисляется большая часть потока. Итак, теперь поместите s (3)
в оболочку, которая вернет res0: Int = 2
. Теперь поместите s
в оболочку, и вы увидите новое значение res1: Stream [Int] = Stream (1, 2, 3, 2,?)
.
Единственный метод, который я смог найти, который содержал нужную вам информацию, к сожалению, был s.toString
. После некоторого синтаксического анализа вы сможете вернуть элементы из строки. Это едва ли приемлемое решение только с целыми числами, и я не мог представить себе какое-либо универсальное решение, использующее идею синтаксического анализа строк.