2015-09-07 19 views
1
Stream(1,2,3,4).map(_+10).filter(_%2==0).toList 

我很好奇上層表達式應該由一個元素執行一個元素而沒有臨時輸出(第一級循環)的原因。例如,Stream class的原因可以用於'第一級循環'

cons(11, Stream(2,3,4).map(_+10)).filter(_%2==0).toList 
cons(12, Stream(3,4).map(_+10)).filter(_%2==0).toList 
12 :: cons(13, Stream(4).map(_+10)).filter(_%2==0).toList 
12 :: 14 :: List() 

由於沒有用於更改執行順序的額外命令。 我想執行次序想此,

cons(11, Stream(2,3,4).map(_+10)).filter(_%2==0).toList 
cons(11, cons(12, Stream(3,4).map(_+10))).filter(_%2==0).toList 
cons(11, cons(12, cons(13, Stream(4).map(_+10)))).filter(_%2==0).toList 
cons(11, cons(12, cons(13, cons(14, Empty))))).filter(_%2==0).toList 
. 
. 
12 :: 14 :: List() 

因爲映射命令是lefter比過濾器命令。

...我寫這篇文章時,我意識到有可能是另一個規則:

「外命令首先,內部命令後」

和這個「外 - >內」的規則來快於「左 - 右」規則。因此,下面的內部映射命令比下面的外部過濾命令慢。

cons(11, Stream(2,3,4).map(_+10)).filter(_%2==0).toList 

我的想法是對的嗎?

回答

2

由於流是惰性的,每個元素都是在「根據需要」的基礎上進行評估的。考慮下面的示例流:

val es = Stream(2,3,4).map(x=>{println("add");x+10}) 
         .filter(x=>{println("filt");x%2==0}) 

第一個元素用流的定義進行評估,但沒有別的,直到你問它。

scala> es(0) 
res314: Int = 12 

scala> es(1) 
add 
filt 
add 
filt 
res315: Int = 14 

想想這樣一來,當我問es(1)它通過map(加10)「拉」 3,但未能通過filter來獲得。由於我們仍然沒有下一個es()元素,我們不得不通過map拉動4,這次它通過了filter步驟。

+0

嗯...我已經知道懶惰,但我很混亂,因爲命令'Stream(1,2,3,4).map(_ + 10).filter(_%2 == 0).toList'問所有值都要評估。 – Curycu

+1

確實,'toList'會通過鏈條拉取所有元素,但它們仍然每次只評估一個。 – jwvh

+0

啊哈...我明白了! '.toList'是這個問題的關鍵!非常感謝 :) – Curycu

相關問題