Range problem

From the Pickaxe book:

class VU
include Comparable

attr :volume

def initialize(volume) # 0…9
@volume = volume
end

def inspect
’#’ * @volume
end

Support for ranges

def <=>(other)
self.volume <=> other.volume
end

def succ
raise(IndexError, “Volume too big”) if @volume >= 9
VU.new(@volume.succ)
end
end

irb(main):001:0> require ‘vu’
=> true
irb(main):002:0> r = VU.new(0)…VU.new(9)
=> …#########
irb(main):003:0> r.to_a
IndexError: Volume too big
from ./vu.rb:20:in succ' from (irb):3:ineach’
from (irb):3:in `to_a’
from (irb):3

Shouldn’t the 0 to 9 range be possible?
Apparently 0 to 8 etc. works.
The succ method should only be raising the exception when @volume is 9
but to me it looks like it’s raising the error at 8.

I’m not sure if it’s a bug or something I’m doing wrong.

Hi –

···

On Fri, 14 May 2004, Rasputin wrote:

From the Pickaxe book:

class VU
include Comparable

attr :volume

def initialize(volume) # 0…9
@volume = volume
end

def inspect
‘#’ * @volume
end

Support for ranges

def <=>(other)
self.volume <=> other.volume
end

def succ
raise(IndexError, “Volume too big”) if @volume >= 9

Should that be > rather than >= ?

David


David A. Black
dblack@wobblini.net

Hi,

At Fri, 14 May 2004 19:48:52 +0900,
Rasputin wrote in [ruby-talk:100269]:

Shouldn’t the 0 to 9 range be possible?
Apparently 0 to 8 etc. works.
The succ method should only be raising the exception when @volume is 9
but to me it looks like it’s raising the error at 8.

I’m not sure if it’s a bug or something I’m doing wrong.

I think it’s a bug.

Index: range.c

···

===================================================================
RCS file: /cvs/ruby/src/ruby/range.c,v
retrieving revision 1.63
diff -u -2 -p -r1.63 range.c
— range.c 30 Dec 2003 16:36:05 -0000 1.63
+++ range.c 14 May 2004 11:07:43 -0000
@@ -142,15 +142,4 @@ range_eq(range, obj)

static int
-r_lt(a, b)

  • VALUE a, b;
    -{
  • VALUE r = rb_funcall(a, id_cmp, 1, b);
  • if (NIL_P(r)) return Qfalse;
  • if (rb_cmpint(r, a, b) < 0) return Qtrue;
  • return Qfalse;
    -}

-static int
r_le(a, b)
VALUE a, b;
@@ -158,7 +147,6 @@ r_le(a, b)
VALUE r = rb_funcall(a, id_cmp, 1, b);

  • if (NIL_P(r)) return Qfalse;
  • if (rb_cmpint(r, a, b) <= 0) return Qtrue;
  • return Qfalse;
  • if (NIL_P(r)) return -1;
  • return 1 - rb_cmpint(r, a, b);
    }

@@ -248,6 +236,8 @@ range_each_func(range, func, v, e, arg)
void *arg;
{

  • int c;
  • if (EXCL(range)) {
  • while (r_lt(v, e)) {
  • while ((c = r_le(v, e)) > 1) {
    (*func)(v, arg);
    v = rb_funcall(v, id_succ, 0, 0);
    @@ -255,6 +245,7 @@ range_each_func(range, func, v, e, arg)
    }
    else {
  • while (r_le(v, e)) {
  • while ((c = r_le(v, e)) > 0) {
    (*func)(v, arg);
  •   if (c == 1) break;
      v = rb_funcall(v, id_succ, 0, 0);
    
    }
    @@ -611,11 +602,6 @@ range_include(range, val)
    beg = rb_ivar_get(range, id_beg);
    end = rb_ivar_get(range, id_end);
  • if (r_le(beg, val)) {
  • if (EXCL(range)) {
  •   if (r_lt(val, end)) return Qtrue;
    
  • }
  • else {
  •   if (r_le(val, end)) return Qtrue;
    
  • }
  • if (r_le(beg, val) > 0) {
  • if (r_le(val, end) > EXCL(range)) return Qtrue;
    }
    return Qfalse;


Nobu Nakada