Streams可以用作类构造函数参数:
scala> ( 0 to 10).toStream.map(i =>{println("bla" + i); -i})
bla0
res0: scala.collection.immutable.Stream[Int] = Stream(0, ?)
scala> class B(val a:Seq[Int]){println(a.tail.head)}
defined class B
scala> new B(res0)
bla1
-1
res1: B = B@fdb84e
因此,尽管作为Seq参数传递,但Stream并未得到完全评估,尽管部分评估。按预期工作。
我有一个这样的课程:
class HazelSimpleResultSet[T] (col: Seq[T], comparator:Comparator[T]) extends HGRandomAccessResult[T] with CountMe
{
val foo: Int = -1 // col of type Stream[T] already fully evaluated here.
def count = col.size
....
}
其中HGRandomAccessResult和CountMe是简单的接口。
在大多数情况下,我想使用Streams作为col构造函数参数,以避免代价高昂的操作。在调试器中我可以遵循它在某些情况下有效,因为即使在初始化HazelSimpleResultSet之后,col显示的值仍然是Stream(xy,?)和“tlVal = null”。
此外,为了进行测试,我将println包含在构成Streams的块中,如下所示:
keyvalues.foldLeft(Stream.empty[KeyType]){ case (a, b) => ({ println("evaluating "+ b); unpack[KeyType](b)}) #:: a}
以便在确切评估Stream时在控制台中关注。
因此,在某些情况下它可以工作,但在某些情况下,在HazelSimpleResultSet初始化的最初时刻,Stream会得到完整的评估。我看不到Stream传递的相关差异,我只是确定他们是无价值的Streams直到那一刻。 使用调试器“进入”,我可以看到它在类定义本身的行中被评估,甚至在到达类体之前,即在任何字段的初始化之前。
修改: 我可以用(次优)方式定义类,这样根本就没有字段引用Stream,但我仍然得到了这种行为。
CountMe接口定义了一个“count”方法,该方法调用col.size然后评估所有Stream。我尝试用懒惰的val大小来定义计数,但这没有什么区别。
我有点不知道为什么它在某些情况下不起作用。任何人都有关于Streams隐藏警告的任何提示吗?
编辑: 一个重要的注意事项:Stream对象包含一些需要评估的严重状态,即对NoSQL数据库的引用(hazelcast)。 问题:这里有什么警告?当我的Stream带有评估所需的有状态引用时,我是否必须注意一些事项?
答案 0 :(得分:1)
如果你这样创建Stream
:
Stream ({println("eval 1"); 1}, {println("eval 2"); 2})
然后你实际上正在调用Stream.apply
,它实现如下:
/** A stream consisting of given elements */
override def apply[A](xs: A*): Stream[A] = xs.toStream
这意味着实际发生的是:
Seq
。Stream
Seq
醇>
正如您所看到的,如果您以这种方式创建Stream
,则会急切地评估其所有元素。这不是你如何创建懒惰评估的Stream
。您想要做的可能是使用#::
和#:::
运算符来懒惰地评估它们的操作数。查看the docs的使用情况。