1

これは、呼び出しごとに新しい proc を生成する ruby​​ 1.8.7 の Symbol#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

これにより、約 1000 個のアレイが作成されていることがわかります。これにより、約 1000 個が空であることがわかります。

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

もう 1 つの興味深い点は、Proc オブジェクトが 1 つしか存在しないことです。to_procこれは、が一度だけ呼び出されることを示唆しています。(もう一度シンボルを呼び出す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 でないのはいつですか?)

4

1 に答える 1

0

私は答えを見つけたと思います。

私はactivesupport 2.2を見て、これがの本体であることがわかりましたSymbol#to_proc:

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

args配列です。範囲の各メンバーは単一の引数として渡されるため、1 要素の配列に変換されます。その 1 つの要素がシフト オフされ、空の配列が残ります。したがって、空の配列を作成するのではなく、引数を処理した後にそれらを残すだけです。

また、2 引数の proc を使用してテストを行いました。

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

これにより、1 要素の配列が残ります (元の最初の要素は現在の合計です)。

私の推測では、1.8.7 も同様のことを行うと思います。1.9 ではどう違うのか知りたいです。

于 2012-08-02T16:59:35.573 に答える