2012-08-02 105 views
1

這是關於此answer的後續,關於ruby 1.8.7的符號#to_proc每次調用都會生成一個新的proc。紅寶石1.8.7 to_proc創建空陣列

似乎有更多的事情比答案建議。

下面是一些示例代碼:

def ctob 
    h=Hash.new(0) 
    ObjectSpace.each_object(Object) {|e| h[e.class]+=1 } 
    h 
end 
r=(0...1000) 
p ctob 
r.map(&:to_i) 
p ctob 

這表明正在創造大約有一千陣列。這表明大約有一千個是空的:

c=0; ObjectSpace.each_object(Array){|e| c+=1 if e.empty? } 

另一個有趣的事情是,只有一個Proc對象存在。這表明to_proc只被調用一次。 (如果我第二次使用符號調用map,可能會創建另一個。)

如果我更改地圖調用以使用塊,則不會創建這些數組。這也可以解釋爲什麼Andrew Grimm的緩存對基準測試沒有幫助。爲什麼創建這些數組?

UPDATE

顯然是從一個符號創建一個進程創建每次被稱爲時間空數組。

如果我更換map線上面

pr=:to_i.to_proc; r.map(&pr) 

導致創建陣列,但這種

pr=proc{|e|e.to_i}; r.map(&pr) 

沒有。類似的事情發生,如果我只做pr.call(價值)。

(何時是proc不是proc?)

回答

0

我想我找到了答案。

我看着的ActiveSupport 2.2,發現這爲Symbol#to_proc體:

Proc.new { |*args| args.shift.__send__(self, *args) } 

args是數組。由於範圍的每個成員都作爲單個參數傳遞,因此它將轉換爲1個元素的數組。這一個元素被移出,留下一個空的數組。所以它不會創建空數組,它只是在處理參數後纔將它們留在後面。

我使用2 ARG PROC也做了測試:

[1,2,3,4].inject(&:+) 

這留下1個元件的陣列(原始第一元件是當前總和)。

我的假設是1.8.7做了類似的事情。我很想知道1.9是如何改變它的。