根據您使用的確切的Ruby實現,Enumerable#map
的實現可以使用Ruby,Smalltalk,RPython,ECMAScript,C#,Java,Go,Objective-C,C++,C或任意數量的其他語言編寫,但它的運作總是會看起來像這樣:
module Enumerable
def map
return enum_for(__method__) unless block_given?
[].tap {|result| each {|el| result << yield el }}
end
end
map
必須呼叫each
,有簡單的爲它遍歷沒有其他辦法。因此,它將分配與each
將分配的確切相同的對象加附加結果Array
,即恰好比each
多一個對象。
實際上,許多Ruby實現覆蓋Enumerable#map
與Array#map
,這比通用的Enumerable
版本更有效。他們通常遍歷直接Array
元素,而不調用each
,有點像這樣:
class Array
def map
return enum_for(__method__) unless block_given?
result = []
i = -1
while i += 1 <= size
result << yield @__entries__[i]
end
end
end
這比一般的Enumerable#map
更有效,因爲它使用如何才能避免重複的Array
專業知識方法調用開銷爲each
。但是請注意,這each
將在完全相同的方式來實現,除非實現者是令人難以置信的愚蠢,所以最終的結果是一樣的:map
仍然會分配恰好一個對象超過each
,它只是一個保存方法調用。
請注意,由於您忽略了map
的返回值,所以額外的對象將立即適用於垃圾回收。但是,在此之前,它保存對deliver_later
方法返回的所有對象的引用,無論它們是什麼。
所以,兩段代碼之間的區別是:
- 與
each
的deliver_later
返回值被忽略,變得適合立即
- 與
map
垃圾收集,還有額外的Array
分配它保持塊內所有deliver_later
調用的返回值的引用,並因此保持這些對象一直存在,直到調用map
返回,然後,Array
,因此它引用的所有對象將同時有資格進行垃圾回收
爲什麼在這種情況下會使用'map'? –
我認爲'.map'會返回一個指向每個創建對象的對象。 '.each'不會。我有一臺工作機器會在內存泄漏之前崩潰 - 所有這一切都發生在這個僞代碼示例是中心操作的事件中。當我將它從'.each'改爲'.map'時,內存泄漏就停止了,但我不知道GC是由於這些方法而發生的。 –
您可以在運行該循環之前自行計算對象,並在使用http://ruby-doc.org/core-2.2.0/ObjectSpace.html#count_objects-method運行該對象並查看是否分配了更多對象之後,我懷疑是否會有任何區別 – bjhaid