1

I can write a short example that verifies that to_a of Enumerable calls each internally. Here it is:

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

The output is:

let us convert to array
each is now called

Note that each is not member of Enumerable, but to_a is. Also, if I remove the definition of each from my class, then code crashes with the following message:

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

I am wondering whether there is Ruby official documentation about this, that would document the fact that to_a (which is member of Enumerable) goes through each method in your class. Please, do not direct me to source code of to_a. I do not consider this an answer.

p.matsinopoulos
  • 7,655
  • 6
  • 44
  • 92

3 Answers3

5

From the fine manual:

The Enumerable mixin provides collection classes with several traversal and searching methods, and with the ability to sort. The class must provide a method each, which yields successive members of the collection.

Emphasis mine. So all of the iterative behavior of Enumerable is based on the class's each method; the ordering parts of the Enumerable interface (min, max, sort) use <=> but that's not important here.

The supplied each method is the only defined way that Enumerable has to interact with the class that mixes it in. Enumerable supplies a to_a method so it must use each to implement it.

As an aside, Enumerable does its best not to call to_a unless it has to, it tries to keep everything as an Enumerable to avoid having to exhaust the enumeration to build an Array that could be expensive in both time and space. The answer that Yossi pointed out is more about when Enumerable calls to_a rather than how (but that answer is interesting reading nonetheless ;).

Community
  • 1
  • 1
mu is too short
  • 426,620
  • 70
  • 833
  • 800
1

Note the id_each in the code of #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;
}

For deeper explanation see this question.

Community
  • 1
  • 1
Yossi
  • 11,778
  • 2
  • 53
  • 66
0

Besides the ascetic explanation in the manual which mu pointed to, there is following passage in Pickaxe book as well, which is defacto king of Ruby introductory books:

Well, your classes can support all these neat-o features, thanks to the magic of mixins and module Enumerable. All you have to do is write an iterator called each, which returns the elements of your collection in turn. Mix in Enumerable, and suddenly your class supports things such as map, include?, and find_all?.

Mladen Jablanović
  • 43,461
  • 10
  • 90
  • 113