【问题标题】:ruby 1.8.7 to_proc creates empty arraysruby 1.8.7 to_proc 创建空数组
【发布时间】:2012-08-02 16:24:22
【问题描述】:

这是answer 的后续,关于 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,也许会创建另一个。)

如果我将 map 调用更改为使用块,则不会创建这些数组。这也可以解释为什么 Andrew Grimm 的缓存对基准测试没有帮助。为什么要创建这些数组?

更新

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

如果我将上面的 map 行替换为

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

导致数组被创建,但这

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

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

(什么时候proc不是proc?)

【问题讨论】:

    标签: ruby ruby-1.8.7


    【解决方案1】:

    我想我找到了答案。

    我查看了activesupport 2.2,发现这是Symbol#to_proc的正文:

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

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

    我还使用 2-arg proc 进行了测试:

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

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

    我的假设是 1.8.7 做了类似的事情。我很想知道 1.9 有什么不同。

    【讨论】:

      猜你喜欢
      • 2011-09-23
      • 2019-01-26
      • 2011-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多