Есть ли в Ruby документация, которая может проверить, что Enumerable.to_a вызывает каждый из них? - PullRequest
1 голос
/ 12 сентября 2011

Я могу написать короткий пример, который подтверждает, что 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. Я не считаю это ответом.

Ответы [ 3 ]

5 голосов
/ 12 сентября 2011

Из тонкого руководства :

* * * * * * * * * * * * * * * * * * * * * * * * * * * * *}}} * * * * * * *}}} Класс должен предоставить метод each, который возвращает последовательных членов коллекции.

Выделить мой.Таким образом, все итеративное поведение Enumerable основано на методе класса each;упорядочивающие части интерфейса Enumerable (min, max, sort) используют <=>, но здесь это не важно.

Предоставленный метод each является единственным определенным способом, которым Enumerable обладаетвзаимодействовать с классом, который его смешивает. Enumerable предоставляет метод to_a, поэтому он должен использовать each для его реализации.

В качестве отступления Enumerable старается не вызывать to_a, если только онон пытается сохранить все как перечисляемое, чтобы избежать необходимости исчерпывать перечисление для создания массива, который может быть дорогим как во времени, так и в пространстве.Ответ, который указал Йосси , больше касается , когда Перечислимые вызовы to_a, а не как (но этот ответ, тем не менее, интересно читать;).

1 голос
/ 12 сентября 2011

Обратите внимание на 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;
}

Более подробное объяснение см. в этом вопросе.

0 голосов
/ 12 сентября 2011

Помимо аскетического объяснения в руководстве, на которое указывал мю, в книге «Кирка» есть также следующий отрывок , который является королем дефективных вводных книг по Ruby:

НуВаши классы могут поддерживать все эти функции, благодаря волшебству mixins и модуля Enumerable.Все, что вам нужно сделать, это написать итератор с именем each, который по очереди возвращает элементы вашей коллекции.Смешайте Enumerable, и вдруг ваш класс поддерживает такие вещи, как map, include? И find_all?.

...