2011-11-06 62 views
8

我在閱讀「Programming in Scala 2ed」。在第24.4節中,注意到Iterable包含許多方法,如果沒有迭代器就無法高效寫入。表24.2包含這些方法。但是,我不明白爲什麼其中一些不能有效地在迭代器上實現。例如,考慮zipWithIndex。爲什麼在Iterable中實現zipWithIndex而不是Traversable?

def zipWithIndex[A1 >: A, That](implicit bf: CanBuildFrom[Repr, (A1, Int), That]): That = { 
    val b = bf(repr) 
    var i = 0 
    for (x <- this) { 
     b += ((x, i)) 
     i +=1 
    } 
    b.result 
    } 

爲什麼不將此定義移動到可遍歷?在我看來,代碼可以完全相同,並且在效率方面沒有區別。

+0

只是想添加一個用例'zipWithIndex'上'Traversable的'。如果你正在實現一種從遍歷中選擇隨機元素的方法呢?在迭代元素時,即使索引不符合具有結構的持久位置,也需要索引來幫助處理概率。 – schmmd

回答

11

你是完全正確的,你的實現應該工作。沒有理由在Iterable中定義zipWithIndex而不是Traversable;既不能保證遍歷中元素的排序。

(這是我在計算器上。希望第一個回答我一直有幫助。:)如果我沒有,請告訴我。)

+0

完全有用,你有+6!我只是確保我沒有遺漏某些東西,因爲本章明確指出表中的方法是在Iterable中實現的,因爲它們在那裏更容易或更高效。 – schmmd

10

Traversable不保證其中的元素將被訪問的順序,只需要你定義具有以下簽名一個foreach方法:

def foreach[U](f: Elem => U): Unit 

由於這種方法只需要調用f對每個元素任何順序,因爲對於每個調用foreach的順序可能不同,所以對元素有索引是沒有意義的。

編輯:這實際上只是一個解釋,爲什麼它不在Traversable上。正如Luigi在評論中指出的那樣,zipWithIndex在Seq上更有意義。

+1

我同意索引在「Traversable」上本身不是有意義的(例如考慮圖)。尤其是,您將無法對獲取的索引*進行任何操作*。但是你可能希望有「循環」索引用於別的東西(並且只是爲了模仿在典型的Java風格的for循環中擁有'i'),爲什麼不呢? – Raphael

+1

'Iterable'(包含地圖和集合)並不保證元素訪問的順序。一個更好的問題會問爲什麼在'Iterable'而不是'Seq'上定義了'zipWithIndex'。 –

+0

經過本次討論後,似乎foreach對於Traversable(爲什麼不)或Seq(保證順序)更有意義! – schmmd

相關問題