From: Dave Date: 2002-01-27T10:13:33+09:00 Subject: Re: Why isn't Range Comparable? On Sat, 26 Jan 2002 23:28:31 GMT, Niklas Frykholm wrote: >[Dave]: >> If a Range is an ordered set, which depends on it's members having >> '<=>' and succ() methods, then why is there no Range#<=>, so to speak? >> This simple experiment seems to work fine with a Range of Fixnums, but >> I haven't tried other object types yet: >> >> irb(main):016:0* class Range >> irb(main):017:1> def <=>(other) >> irb(main):018:2> return 0 if self.member?(other) >> irb(main):019:2> return -1 if other < self.begin >> irb(main):020:2> return 1 if other > self.end >> irb(main):021:2> raise "Bogus!" >> irb(main):022:2> end >> irb(main):023:1> end >> >> irb(main):025:0> (1..10) <=> 11 >> 1 >> irb(main):026:0> (1..10) <=> 0 >> -1 >> irb(main):027:0> (1..10) <=> 1 >> 0 > >(You probably have -1 and 1 inverted above.) Oops, of course, you're right. >#<=> is usually used to compare objects of the same class, since ranges >are not comparable, calling this method #<=> is probably confusing. > >I'm not even sure fixnums and ranges of fixnums can always be compared >in a sane manner. What would you have this return. > > (10..1) <=> 3 Ah, well, I guess I am not really comparing with the range, but with elements of the range. I would have (10..1) <=> 3 --> 0, because regardless of their placement in the Range, that's the way the element comparison would go. I'll have to think of a better name for what I'm getting at. A sort of a more-informative member? method is what I'm after. Speaking of #member?, I was doing some profiling and noticed that it appears that Range#member? (really Enumerable.member? ) implemented by iterating through self.each. I wrote a method based on the above ideas, and found it much, much faster: class Range def fastmember?(other) return true if ( self.begin <= other && other <= self.end ) return false end end For example, for an input file of 10,000 random alpha strings of random lengths between 1 and 63 chars, the following ran about 5.5 times faster than using method? range = (1..63) STDIN.each_line do |string| range.fastmember? string.length end