From: matz@... (Yukihiro Matsumoto) Date: 2003-02-12T03:23:13+09:00 Subject: Re: Range#length?!?!? Hi, In message "Re: Range#length?!?!?" on 03/02/12, ahoward writes: |IMHO this makes _perfect_ sense : | | class Range | def size | case first | when String | a = i = 0 | first.reverse.each_byte do |byte| | a += byte * (256 ** i) and i += 1 | end | b = i = 0 | last.reverse.each_byte do |byte| | b += byte * (256 ** i) and i += 1 | end | return b - a + (exclude_end? ? 0 : 1) | when Float | return 1.0/0.0 | end | end | end | | p ('a' .. 'a').size # => 1 | p ('a' ... 'a').size # => 0 | p ('a' .. 'z').size # => 26 | p ('a' ... 'z').size # => 25 | p ('aa' ... 'aa').size # => 0 | p ('aa' .. 'ab').size # => 2 | p ('aa' ... 'ab').size # => 1 | p ('aa' ... 'zz').size # => 6425 | | p (0.0 ... 42.0).size # => Infinity Interesting. |this length of a String Range is easily calculated by interpreting a string as |a base 256 number, eg: | | 'abc' -> 'a'[0] * (256 ** 2) + 'b'[0] * (256 ** 1) + 'c'[0] * (256 ** 0) | |which makes it very inexpesive (and entirely accurate) to calculate especially |since the 'normal' String ranges are made up of quite short strings. | |p ('even this' ... 'works quickly').size # => 9462642498376336060692356596486 But 'even this' never reaches 'works quickly' under the current String#succ behavior. for x in 'even this' ... 'works quickly' ... end would be an infinite loop. Do you want to change how it works (to something doesn't work for multibyte characters)? |it also seems to make perfect sense for Float Ranges to have size Infinity? |this would suprise no one. On the contrary, for x in 0.0 ... 42.0 ... end stops. matz.