Question about NUM2LONG, symbols

Hi all,

The various NUM2x functions (NUM2LONG, NUM2INT, etc) include builtin type checks. However, they still seem to blindly accept symbols. Why?

/* foo.c */
#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);
}

# foo.rb
require "foo"

Foo.new.test("foo") # TypeError, expected
Foo.new.test("foo".to_sym) # NUM: 10201 - yikes!

Regards,

Dan

Foo.new.test("foo".to_sym) # NUM: 10201 - yikes!

moulon% cat aa.c
#include "ruby.h"
#include <stdio.h>

static VALUE
aa_to_int(VALUE self)
{
    return INT2FIX(12);
}

static VALUE
aa_test(VALUE self)
{
    printf("NUM: %ld\n", NUM2LONG(self));

   return Qnil;
}

void Init_aa(){
   VALUE cAa = rb_define_class("Aa", rb_cObject);
   rb_define_method(cAa, "test", aa_test, 0);
   rb_define_method(cAa, "to_int", aa_to_int, 0);
}

moulon%

moulon% ruby -raa -e 'Aa.new.test'
NUM: 12
moulon%

Guy Decoux

ts wrote:

"D" == Daniel Berger <Daniel.Berger@qwest.com> writes:

> Foo.new.test("foo".to_sym) # NUM: 10201 - yikes!

moulon% cat aa.c
#include "ruby.h"
#include <stdio.h>

static VALUE
aa_to_int(VALUE self)
{
    return INT2FIX(12);
}

static VALUE aa_test(VALUE self)
{
    printf("NUM: %ld\n", NUM2LONG(self));

   return Qnil;
}

void Init_aa(){
   VALUE cAa = rb_define_class("Aa", rb_cObject);
   rb_define_method(cAa, "test", aa_test, 0);
   rb_define_method(cAa, "to_int", aa_to_int, 0);
}

moulon%

moulon% ruby -raa -e 'Aa.new.test'
NUM: 12
moulon%

Guy Decoux

Ok, thanks Guy, I get it - internally it calls rb_num2long(), which in turn tries to call a to_int method. Since the Symbol class defines to_int, I get that result.

I guess it would be nice if we had a macro that raised a TypeError on anything except a Fixnum, Float or Bignum. Otherwise, aren't all C extension writers relegated to doing explicit checks against Symbols (the way rb_ary_ref() does in array.c) if we really want to make our code bulletproof? That, or lots of Check_Type() functions sprinkled throughout our code?

I suppose I just want a version of rb_num2long() that changes the default in the switch statement to something like this:

default:
    rb_raise(rb_eTypeError, "not a Fixnum, Float or Bignum");

Thanks,

Dan

Hi,

At Fri, 4 Nov 2005 02:02:35 +0900,
Daniel Berger wrote in [ruby-talk:163946]:

I guess it would be nice if we had a macro that raised a TypeError on anything
except a Fixnum, Float or Bignum. Otherwise, aren't all C extension writers
relegated to doing explicit checks against Symbols (the way rb_ary_ref() does
in array.c) if we really want to make our code bulletproof? That, or lots of
Check_Type() functions sprinkled throughout our code?

An object has :to_int method should be treated as an Integer.
It's duck-typing, isn't it? Symbol no longer has that method
in 1.9.

···

--
Nobu Nakada

I understand the duck typing approach. However, I'm curious why
rb_ary_aref() explicitly forbids symbols as arguments. Can you tell me
why? Was there some unexpected side effect?

Thanks,

Dan

···

nobu.nokada@softhome.net wrote:

Hi,

At Fri, 4 Nov 2005 02:02:35 +0900,
Daniel Berger wrote in [ruby-talk:163946]:
> I guess it would be nice if we had a macro that raised a TypeError on anything
> except a Fixnum, Float or Bignum. Otherwise, aren't all C extension writers
> relegated to doing explicit checks against Symbols (the way rb_ary_ref() does
> in array.c) if we really want to make our code bulletproof? That, or lots of
> Check_Type() functions sprinkled throughout our code?

An object has :to_int method should be treated as an Integer.
It's duck-typing, isn't it? Symbol no longer has that method
in 1.9.

--
Nobu Nakada

Hi,

At Sat, 5 Nov 2005 09:57:09 +0900,
Daniel Berger wrote in [ruby-talk:164299]:

I understand the duck typing approach. However, I'm curious why
rb_ary_aref() explicitly forbids symbols as arguments. Can you tell me
why? Was there some unexpected side effect?

In older versions, symbols were just integers, so Symbol has
to_int method. But it was considered inappropriate for array
index which is successive. It is like the appendix, and no
longer in 1.9.

···

--
Nobu Nakada