[Oops, first copy accidently got sent to Brian instead of list. Sorry.] On 10/9/2004 6:52 AM, Brian Candler wrote: > On Sat, Oct 09, 2004 at 07:30:09PM +0900, Randy W. Sims wrote: > >>Ahh, ok. I didn't realize set > > > Range > > >>was implemented in this way. I can see why >>you did it: it allows ranges for all types of objects. Very nice. > > > Range#include? just uses the <=> operator to test for the bottom and top of > the range (in other words, it's intended for objects which are Comparable > rather than Enumberable) > > >>Even with this, It would still be nice if membership could be tested... >>efficiently. Or at least efficient for the common cases. Range could be >>special cased for Integers so that a member could be found by >>calculating elements for a "binary search" (if (((end - start) / 2) > >>target))... > > > You can't do a binary search over an Enumberable, because it just gives you > the elements one at a time in order; it doesn't support "fetch Nth item". > You'd have to first enumerate everything into an Array, which brings you > back to the current situation anyway. For some types it is possible to calculate whether a value exist within a range without the need of iterating through the whole range with #succ. Integer, Date, and possibly String could all offer the ability to test if a member is in range by performing a quick calculation. Other types would have to defer to the #succ method. Types that can provide efficient membership test would all support an interface, a #test_in_range(start, end, target) class method, that #member? could query. > Also, if you really want that sort of membership test with integers, then > there's no need for a binary search anyway: > > myrange.include?(x) and x.to_i == x > > ISTM that in Ruby, a range is *primarily* a continuous range with lower and > upper bounds. If the lower bound happens to be an object which responds to > 'succ' to generate the next object in a sequence, and <=> to match the upper > bound, then magically it also becomes Enumerable. I guess it's not really that big of a deal to me. It just seems a little inconsistent. Sometimes a Range seems continuous (#include?) and other times not ((1..5).each {|i| puts i}). I was just trying to think of a way to make it more consistent without a major speed penalty. Randy.