From: Xavier Noria Date: 2007-09-23T02:36:59+09:00 Subject: Re: (SUMMARY) Idiomatic Ruby for Array#extract / Range#length? I think this thread deserves a summary. Sammry Larbi asks three questions in the post that opens this thread, the first one asks whether it would make sense to define Range#length as the difference between its endpoints. The short answer is that objects in ranges do not necessarily respond to #-. Furthermore, according to the docs (Ruby docs and Pickaxe), objects in ranges respond to #succ, and so one may wonder whether you can define Range#length as an element count implemented as a loop from left endpoint to right endpoint via #succ. There's a warning, though, because #<=> and #succ do not guarantee ranges are finite, so such a method is not guaranteed to terminate. That's a claim at that point, and some people ask for further details. There's a split here in the thread (mixed in practice): 1) The docs say so, but there's enough evidence to say they are wrong, objects in ranges are only required to respond to #succ if you want to iterate over them. If you want to implement Range#length that way you have to assume objects respond to #succ anyway. 2) A few examples of classes that give infinite ranges are described or implemented, the most simple of them being the ZSquared class copied below. The other two questions of the original post remain unanswered by now (at least in the mailing list). Best, -- fxn class ZSquared include Comparable attr_reader :n, :m def initialize(n, m) @n, @m = n, m end def succ self.class.new(n+1, m) end def <=>(zs) [self.m, self.n] <=> [zs.m, zs.n] end end a = ZSquared.new(0, 0) b = ZSquared.new(0, 1) puts a < b # true length = 0 (a .. b).each do |c| length += 1 puts length end # be prepared to send Ctrl-C