2013-03-11 66 views
2

流可以作爲類的構造函數的參數:流作爲構造精氨酸在早期類的初始化有時充分評估

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 = [email protected] 

那麼,該流不得到完全雖然交了一個序列參數評估,儘管是部分評估。按預期工作。

我有一類這樣的:

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是簡單的接口。

我大多數情況下我想使用流作爲col構造函數參數,以避免代價高昂的操作。在調試器中,我可以按照它在某些情況下工作,因爲即使在初始化HazelSimpleResultSet後,爲col顯示的值仍然爲Stream(xy,?)和「tlVal = null」。

此外,用於測試,我包括調用println在於構建這樣的流的塊:

keyvalues.foldLeft(Stream.empty[KeyType]){ case (a, b) => ({ println("evaluating "+ b); unpack[KeyType](b)}) #:: a} 

,以便在完全流evaluted在控制檯跟隨。

因此,在某些情況下,它可以工作,但在某些情況下,在HazelSimpleResultSet初始化的第一個時刻,流得到完整評估。我看不到交易中的相關區別,我確信他們是無價值的Streams直到那一刻。 使用調試器「進入」,我可以看到它在類定義本身的行中被評估,甚至在到達類體之前,即在任何字段的初始化之前。

編輯: 我可以在(次優)的方式定義類等無勵磁在所有被引用到的數據流,而我仍然得到這種行爲。

CountMe接口定義了一個「count」方法,它調用col.size然後評估所有的Stream。我試圖用懶惰的val值來定義count,但這並沒有什麼不同。

我有點茫然,爲什麼它在某些情況下不起作用。任何人都有關於Streams隱藏警告的暗示?

編輯: 重要注意事項:Stream對象包含了一些需要評估的嚴重狀態,即對NoSQL數據庫(hazelcast)的引用。 問題:這裏有什麼警告?當我的Stream帶有評估必需的有狀態引用時,是否有特別的事情需要處理?

回答

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 

這意味着實際發生的事情是:

  1. 評估所有元素!
  2. A Seq包含這些元素被創建。
  3. 一個Stream創建出這個Seq

所以你可以看到,如果你創建你Stream這樣一來,它的所有元素都急切地評估。這不是你如何創建懶惰評估Stream。你想要做的可能是使用#::#:::運營商懶惰評估他們的操作。查看the docs的使用情況。

+0

這只是爲了演示。我以有效的方式執行我的Streams,例如:keyvalues.foldLeft(Stream.empty [KeyType]){case(a,b)=>(a ++ Stream(unpack [KeyType](b)))} – ib84 2013-03-11 13:45:18

+0

(edited post) – ib84 2013-03-11 13:51:48

+0

你確定'foldLeft'和'++'使用懶惰評估嗎?我會懷疑他們沒有。 – ghik 2013-03-11 13:51:57