djberg96 ([info]djberg96) wrote,
@ 2005-11-03 09:11:00
Previous Entry  Add to memories!  Tell a Friend  Next Entry
Current mood: confused

NUM2LONG strangeness
While attempting to refactor array.c a little bit, I noticed that the rb_ary_ref() function, the function behind the Array#[] instance method, was performing explicit SYMBOL_P checks. I thought this was odd, because NUM2LONG already has a builtin type check, right?

One little problem - NUM2LONG doesn't seem to mind symbols. If you pass a symbol object to NUM2LONG, it just returns any ol' random number!

#include "ruby.h"
#include <stdio.h>

static VALUE foo_test(VALUE self, VALUE num)
{
   long x;
   x = NUM2LONG(num);

   printf("NUM: %ld\n", x);

   return Qnil;
}

void Init_foo(){
   VALUE cFoo = rb_define_class("Foo", rb_cObject);
   rb_define_method(cFoo, "test", foo_test, 1);
}

# test.rb
f = Foo.new
f.test("foo".to_sym) # 10201! Yikes!


Oofda. Off to the mailing list. Well, knowing this has helped me write better unit tests, at least.

Update: It turns out that NUM2LONG calls rb_num2long() internally if it's not a Fixnum. The rb_num2long() functions falls back to calling the to_int method if it's not a Float or Bignum. Since the Symbol class *does* define a to_int method, you end up with the results of Symbol#to_int. I understand the logic behind this, but we should probably have "strict" versions of these macros as well.



Create an Account
Forgot your login or password?
Login w/ OpenID
English • Español • Deutsch • Русский…