Robert Klemme
7/14/2005 8:26:00 AM
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