您可能會發現它很有用它們分解表達式,並使用IRB或PRY看到什麼紅寶石在做什麼。讓我們先從:
[1,2,3].each_with_index.map { |i,j| i*j }
讓
enum1 = [1,2,3].each_with_index
#=> #<Enumerator: [1, 2, 3]:each_with_index>
我們可以用Enumerable#to_a(或Enumerable#entries),以enum1
轉換成數組,看看它會被傳遞到下一個枚舉(或如果一個塊它有一個):
enum1.to_a
#=> [[1, 0], [2, 1], [3, 2]]
那裏沒有什麼驚喜。但是enum1
沒有阻止。相反,我們正在發送它的方法Enumerable#map:
enum2 = enum1.map
#=> #<Enumerator: #<Enumerator: [1, 2, 3]:each_with_index>:map>
你可能會認爲這是一種「複合型」枚舉的。此枚舉確實有一個塊,所以將其轉換爲一個陣列將確認其將通過相同的元件到該塊作爲enum1
將有:
enum2.to_a
#=> [[1, 0], [2, 1], [3, 2]]
我們看到,陣列[1,0]
是第一要素enum2
通入該塊。 「消歧」被施加到這個數組指派的塊的變量的值:
i => 1
j => 0
即,紅寶石設置:
i,j = [1,0]
現在,我們可以通過與發送它的方法each
調用enum2
塊:
enum2.each { |i,j| i*j }
#=> [0, 2, 6]
下考慮:
[1,2,3].map.each_with_index { |i,j| i*j }
我們:
enum3 = [1,2,3].map
#=> #<Enumerator: [1, 2, 3]:map>
enum3.to_a
#=> [1, 2, 3]
enum4 = enum3.each_with_index
#=> #<Enumerator: #<Enumerator: [1, 2, 3]:map>:each_with_index>
enum4.to_a
#=> [[1, 0], [2, 1], [3, 2]]
enum4.each { |i,j| i*j }
#=> [0, 2, 6]
由於enum2
和enum4
傳遞相同的元素融入到塊,我們看到這是在做同樣的事情只有兩個辦法。
這裏的第三相當於鏈:
[1,2,3].map.with_index { |i,j| i*j }
我們:
enum3 = [1,2,3].map
#=> #<Enumerator: [1, 2, 3]:map>
enum3.to_a
#=> [1, 2, 3]
enum5 = enum3.with_index
#=> #<Enumerator: #<Enumerator: [1, 2, 3]:map>:with_index>
enum5.to_a
#=> [[1, 0], [2, 1], [3, 2]]
enum5.each { |i,j| i*j }
#=> [0, 2, 6]
爲了進一步藉此一步,假設我們有:
[1,2,3].select.with_index.with_object({}) { |(i,j),h| ... }
我們:
enum6 = [1,2,3].select
#=> #<Enumerator: [1, 2, 3]:select>
enum6.to_a
#=> [1, 2, 3]
enum7 = enum6.with_index
#=> #<Enumerator: #<Enumerator: [1, 2, 3]:select>:with_index>
enum7.to_a
#=> [[1, 0], [2, 1], [3, 2]]
enum8 = enum7.with_object({})
#=> #<Enumerator: #<Enumerator: #<Enumerator: [1, 2, 3]:
# select>:with_index>:with_object({})>
enum8.to_a
#=> [[[1, 0], {}], [[2, 1], {}], [[3, 2], {}]]
enum8
進入到塊中的第一個元素是數組:然後
(i,j),h = [[1, 0], {}]
消歧被施加到值分配給所述塊的變量:
i => 1
j => 0
h => {}
注意enum8
顯示一個空散列被傳遞在enum8.to_a
的三個元素中的每一箇中,但當然這只是因爲Ruby在第一個元素傳入後不知道哈希將看起來像什麼樣。
很好提出 – Ratatouille