Skip to content

Instantly share code, notes, and snippets.

@markjlorenz
Last active August 29, 2015 14:02
Show Gist options
  • Save markjlorenz/7ac01861edef951d2f5b to your computer and use it in GitHub Desktop.
Save markjlorenz/7ac01861edef951d2f5b to your computer and use it in GitHub Desktop.
One reason that Ruby's documentation isn't great.

One Reason Ruby's Docs Aren't Great

If you followed those links, you might be thinking that I screwed them up. I didn't. Looke closely, and you'll notice that the Fixnum#== docs are actaully repeated twice. Neat.

You might think that's a bug. It's not.

Let's see why:

/* numeric.c  */

/*
 * call-seq:
 *   fix == other  ->  true or false
 *
 * Return +true+ if +fix+ equals +other+ numerically.
 *
 *   1 == 2      #=> false
 *   1 == 1.0    #=> true
 */

static VALUE
fix_equal(VALUE x, VALUE y)
{
    if (x == y) return Qtrue;
    if (FIXNUM_P(y)) return Qfalse;
    else if (RB_TYPE_P(y, T_BIGNUM)) {
	return rb_big_eq(y, x);
    }
    else if (RB_TYPE_P(y, T_FLOAT)) {
        return rb_integer_float_eq(x, y);
    }
    else {
	return num_equal(x, y);
    }
}

So there is this c-lang function fix_equal that implements double equals, but what about ===?

/* numeric.c  */

rb_define_method(rb_cFixnum, "==", fix_equal, 1);
rb_define_method(rb_cFixnum, "===", fix_equal, 1);

ah-ha! so the code that turns the c function fix_equal into a ruby method is doubled up, one for == and one for ===. Neat.


Hold on minute! There are other place in the docs where a method has two names and the docs don't have that confusing duplicate entry, like Fixnum#inspectdoc and Fixnum#to_sdoc. Why?

/* numeric.c  */

/*
 *  call-seq:
 *     fix.to_s(base=10)  ->  string
 *
 *  Returns a string containing the representation of +fix+ radix +base+
 *  (between 2 and 36).
 *
 *     12345.to_s       #=> "12345"
 *     12345.to_s(2)    #=> "11000000111001"
 *     12345.to_s(8)    #=> "30071"
 *     12345.to_s(10)   #=> "12345"
 *     12345.to_s(16)   #=> "3039"
 *     12345.to_s(36)   #=> "9ix"
 *
 */
static VALUE
fix_to_s(int argc, VALUE *argv, VALUE x)
{
    int base;

    if (argc == 0) base = 10;
    else {
	VALUE b;

	rb_scan_args(argc, argv, "01", &b);
	base = NUM2INT(b);
    }

    return rb_fix2str(x, base);
}
/* numeric.c  */

rb_define_method(rb_cFixnum, "to_s", fix_to_s, -1);
rb_define_alias(rb_cFixnum, "inspect", "to_s");

Huh. The only difference that rb_define_alias was used to define Fixnum#inspect. Why does ruby do it two different (synonym and alias) and confusing ways? I have no idea.

-- Mark!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment