Levin Alexander wrote:
> Robert Klemme <bob.news / gmx.net> wrote:
>
>>> Interesting.  I would lean towards (b) (which I believe is the
>>> current implementation if exclude_end? is false).
>>
>> In that case the inclusion of Enumerable becomes questionable.
>
> But Ranges have many other uses which depend on it being Enumerable

Yeah, certainly.

>>> (a) is not really practical because Range is not always Enumerable
>>> and this also conflicts with my mental model of a "Range"
>>
>> Right:
>>
>>>> (1.5 .. 3.4).to_a
>> TypeError: cannot iterate from Float
>>         from (irb):14:in `each'
>>         from (irb):14:in `to_a'
>>         from (irb):14
>>
>> We have the weired situation that a Range where left and right are
>> enumerable (integers, strings) the inclusion of Enumerable is ok and
>> for
>
> A range is only Enumerable if the left side defines +succ+
>
>    >> (0..Math::PI).to_a
>    => [0, 1, 2, 3]
>    >> class Float; def succ; self+0.8; end; end;
>    => nil
>    >> (0.1..2.0).to_a
>    => [0.1, 0.9, 1.7]
>
>> non enumerable types (Float) it's not.  That's a bit weired situation
>> IMHO, at least not exactly good design.
>
> I don't believe that it is much of a problem in practice.

Yeah, probably.  Since generally Ruby favours pragmatic solutions over
formally more correct solutions we probably should leave it as is.  In
fact, I haven't tripped into that trap yet. :-)

> Maybe Range should have a method enumerable? so that you can check if
> each is going to work before you actually use it.
>
>    class Range
>      def enumerable?
>        first.respond_to?(:succ)
>      end
>    end
>
>    r = (1..10)
>    arr = r.enumerable? ? r.entries : []

Yeah, probably.  Though I would not dare to guess how often this is really
needed...

Kind regards

    robert