2017-01-13 10 views
6

В Ruby 2.4 и для целых диапазонов Range(Enumerable)#sum - это optimized, чтобы возвращать результат напрямую, без повторения всех элементов.Почему сумма Range # определена в Enumerable module?

Я не понимаю, почему соответствующий код определяется в enum.c для Enumerable модуля, а не в range.c для Range класса.

Почему Enumerable знать о классах, которые включают его (например, Range, Hash, ...) и проверить их типа, вместо того, чтобы позволить эти классы перезаписать Enumerable#sum?

замечен в enum.c:

return int_range_sum(beg, end, excl, memo.v); 
# or 
hash_sum(obj, &memo); 
+0

Хороший вопрос. Для меня логичнее делать то, что вы предлагаете. –

+1

.. потому что разработчики языка тоже ошибаются? Задать вопрос автору: https://github.com/ruby/ruby/commit/eb9c9964b08b980b05149ce91173204060917468 –

+0

Я не говорю, что это неправильно, просто это удивительно. Там может быть вполне обоснованная причина (например, производительность). –

ответ

6

Поскольку rb_range_values может быть true для произвольных экземпляров классов (не только явные Range ы), и все мы хотим, чтобы они были оптимизированы тоже.

В принципе, это означает, что как только экземпляр отвечает как на begin and endexclude_end? кстати, мы должны ввести эту оптимизацию.

+0

Отлично, спасибо. Я просто попробовал это с классом MyRange; include Enumerable; ... 'и' # sum' отлично работает, если определены 'begin',' end' и 'exclude_end?'. Не могли ли эти произвольные классы наследовать от Range, когда они так похожи на Range? –

+0

«Не могли ли эти экземпляры произвольного класса наследовать от Range, когда они так похожи на Range?» - я определенно не являюсь подходящим человеком для решения этого вопроса :) – mudasobwa

+0

@ EricDuminil, вообще говоря, не хотелось бы наследовать от ядра класс. При этом я согласен с тем, что 'Enumerable # sum' не должен вводить проверку и включать классы, требующие определенной функциональности, для переопределения' # sum' или принятия значения по умолчанию, что приводит к 'Enumerable # sum',' Range # sum' и 'Hash # sum'. Эта реализация переопределения для каждого объекта сохраняется в настоящее время для таких классов, как 'Array' и' Hash', где они реализуют свои собственные версии '# select', поэтому я не вижу, почему' # sum' должно быть любым другим – engineersmnky

 Смежные вопросы

  • Нет связанных вопросов^_^