ruby 1.8.7 to proc创建空数组



这是这个答案的后续,关于ruby 1.8.7的Symbol#to_proc在每次调用时生成一个新的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的缓存对基准测试没有帮助。为什么要创建这些阵列?

更新

显然,从Symbol创建的进程每次被调用时都会创建一个空数组。

如果我用替换上面的map

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

导致创建阵列,但此

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

没有。如果我只做pr.call(value).,也会发生类似的事情

(什么时候进程不是进程?)

我想我找到了答案。

我查看了activesupport 2.2,发现它是Symbol#to_proc:的主体

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

args是数组。由于范围的每个成员都作为单个arg传递,因此它被转换为一个由1个元素组成的数组。这一个元素被偏移掉,留下一个空数组。因此,它不是在创建空数组,而是在处理参数后将它们留下。

我还用2-arg程序做了一个测试:

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

这留下了1个元素的数组(原始的第一个元素是当前的和)。

我的假设是1.8.7也有类似的作用。我很想知道1.9的不同之处。

最新更新