1

内部to_aでのEnumerable呼び出しを検証する短い例を書くことができます。eachここにあります:

class MyFooClass
  include Enumerable
  def initialize
    @members = [1, 2, 3]
  end
  def each
    puts "each is now called"
    @members.each{ |m| yield(m) }
  end
end

a = MyFooClass.new
puts "let us convert to array"
g = a.to_a

出力は次のとおりです。

let us convert to array
each is now called

eachはのメンバーではありませんが、のメンバーであるEnumerableことに注意してくださいto_a。また、クラスからの定義を削除するとeach、コードがクラッシュして次のメッセージが表示されます。

in `to_a': undefined method `each' for #<MyFooClass:0x997c1ac @members=[1, 2, 3]> (NoMethodError)

これに関するRubyの公式ドキュメントがあるかどうか疑問に思っています。to_aこれは、(のメンバーである)がクラスのメソッドをEnumerable通過するという事実をドキュメント化するものです。eachのソースコードを教えてはいけませんto_a。私はこれを答えとは考えていません。

4

3 に答える 3

5

細かいマニュアルから:

ミックスインは、いくつかのEnumerableトラバーサルメソッドと検索メソッド、およびソート機能を備えたコレクションクラスを提供します。クラスeachは、コレクションの連続するメンバーを生成するメソッドを提供する必要があります。

強調鉱山。eachしたがって、Enumerableの反復動作はすべて、クラスのメソッドに基づいています。minEnumerableインターフェイス( 、、 )の順序付け部分は使用しますがmax、ここでは重要ではありません。sort<=>

提供されeachたメソッドは、Enumerableがそれを混合するクラスと対話する必要がある唯一の定義された方法です。Enumerableはメソッドを提供するため、それを実装するto_aために使用する必要があります。each

余談ですが、Enumerableは、必要がない限り呼び出さto_aないように最善を尽くします。時間とスペースの両方でコストがかかる可能性のある配列を構築するために列挙を使い果たす必要がないように、すべてをEnumerableとして保持しようとします。Yossiが指摘した答えは、方法ではなくEnumerableがいつ呼び出されるかに関するものです(しかしその答えはそれでも興味深い読み物です;)。to_a

于 2011-09-12T08:44:02.623 に答える
1

id_eachのコードに注意してください#to_a

static VALUE
enum_to_a(int argc, VALUE *argv, VALUE obj)
{
    VALUE ary = rb_ary_new();

    rb_block_call(obj, id_each, argc, argv, collect_all, ary);
    OBJ_INFECT(ary, obj);

    return ary;
}

詳細な説明については、この質問を参照してください。

于 2011-09-12T08:28:07.587 に答える
0

muが指摘したマニュアルの禁欲的な説明に加えて、Rubyの入門書の事実上の王であるPickaxeの本にも次の文章があります。

さて、あなたのクラスは、ミックスインとモジュールEnumerableの魔法のおかげで、これらすべてのきちんとした機能をサポートできます。あなたがしなければならないのは、コレクションの要素を順番に返す、eachというイテレータを書くことだけです。Enumerableを組み合わせると、突然、クラスがmap、include?、find_all?などをサポートします。

于 2011-09-12T09:16:49.207 に答える