2012-10-29 55 views
8

在Coursera繼斯卡拉課程,馬丁·奧德斯基顯示的示例代碼是:爲什麼在地圖操作之後Range被轉換爲Vector?

1 to 5 map (i => i*i) 

他還說,Range被轉化爲Vector,因爲它們共享相同的接口(IndexedSeq)和結果不能代表作爲Range (因爲他產生的一對是不能表示爲一個Range它是在它的例子更清楚)。

我不確定要理解,因爲我認爲他之前說過,在表達式中,第1個生成器將確定將會生成的元素的種類,而且似乎並非總是如此,至少對於Range而言。

我不確定要理解爲什麼輸出爲Vector,因爲Vector可能不是唯一可以表示上面計算結果的其他一個實現。

有人可以幫助我瞭解這部分嗎?

回答

9

map偷偷需要CanBuildFrom作爲隱含參數。它的工作是根據你已經擁有的一個(和內容的類型)生成一個新的集合。由於Range不能包含任意的東西 - 甚至不是任意的整數 - 沒有CanBuildFrom產生Range。具有CanBuildFrom的最具體的超類型RangeIndexedSeq。實際上由此構建的集合是Vector

+1

所以你的意思是Scala默認默認導入一些隱式的CanBuildFroms,並且我最終可以重寫它們或什麼?在這種情況下,是否有可能只是爲了理解而產生別的東西而不是Vector? –

+1

@SebastienLorber - 確實可以!如果某些其他隱含已經可以應用,例如查找「breakOut」也許是最方便的方法。 http://stackoverflow.com/questions/2592024 –

+0

是的,如果你明確提供了一個有效的構建器,你可以得到另一個集合 – Arjan

1

VectorIndexedSeq默認實現。由於Range類被設計爲包含一系列可以由開始來表示,停止數字,和步長值(在Python類似於range)的map不能被表示爲Range。 API文檔指定它是IndexSeq的特例。

我們可以看到1 to 5 map { i => i * i }將得到我們的值(1,4,9,16,25)的容器。我們可以開始和停止,但沒有恆定的階梯值。

2

正如我敢肯定,馬丁還解釋,for推導對應的mapflatMap方法鏈接(被翻譯成)調用(和foreach如果你不使用yield)。

之所以它通常導致第一發生器的類型的值是mapflatMap通常返回相同的類型作爲其接收器(map上的List回報List等)。

現在的問題Range s是他們不能代表不是整數的正則序列的東西。因此,中mapflatMapas defined for Range返回類型不能爲Range。下一個最佳匹配是Vector,一個索引序列的原型實現。 (如果你看源代碼,或者甚至是我鏈接到的Scala文檔頁面,你會發現它稍微複雜一些,只是返回類型,但在概念上,這就是原因。)編輯: ...現在雷克斯克爾剛剛投下了炸彈CanBuildFrom

相關問題