There's a programming language in which Ruby and many Ruby libraries are written, but pretty much nothing else. Let's call it RubyC. It looks a lot like C, and can even be compiled by C compilers, but it's different in many important ways:
- It is garbage-collected
- All functions return one
VALUE
, and all their arguments areVALUE
s - It supports many features of Ruby, usually with just some syntactic overhead. In particular Ruby standard library and object-oriented model are available
Array#sort
:VALUE rb_ary_sort(VALUE ary)
{
ary = rb_ary_dup(ary);
rb_ary_sort_bang(ary);
return ary;
}
Notice that both the argument (from Ruby point of view
ary
is self
), and the return value are VALUE
s, and that it completely ignores memory management - freshly allocated result of rb_ary_dup
is going to manage itself, somehow.Here are a few more snippets. This one sets up
Range
class:void Init_Range()
{
rb_cRange = rb_define_class("Range", rb_cObject);
rb_include_module(rb_cRange, rb_mEnumerable);
rb_define_method(rb_cRange, "initialize", range_initialize, -1);
rb_define_method(rb_cRange, "==", range_eq, 1);
rb_define_method(rb_cRange, "===", range_include, 1);
rb_define_method(rb_cRange, "eql?", range_eql, 1);
rb_define_method(rb_cRange, "hash", range_hash, 0);
rb_define_method(rb_cRange, "each", range_each, 0);
rb_define_method(rb_cRange, "step", range_step, -1);
rb_define_method(rb_cRange, "first", range_first, 0);
rb_define_method(rb_cRange, "last", range_last, 0);
rb_define_method(rb_cRange, "begin", range_first, 0);
rb_define_method(rb_cRange, "end", range_last, 0);
rb_define_method(rb_cRange, "to_s", range_to_s, 0);
rb_define_method(rb_cRange, "inspect", range_inspect, 0);
rb_define_method(rb_cRange, "exclude_end?", range_exclude_end_p, 0);
rb_define_method(rb_cRange, "member?", range_include, 1);
rb_define_method(rb_cRange, "include?", range_include, 1);
id_cmp = rb_intern("<=>");
id_succ = rb_intern("succ");
id_beg = rb_intern("begin");
id_end = rb_intern("end");
id_excl = rb_intern("excl");
}
And this one implements
Float#<=
.static VALUE flo_le(VALUE x, VALUE y)
{
double a, b;
a = RFLOAT(x)->value;
switch (TYPE(y)) {
case T_FIXNUM:
b = (double)FIX2LONG(y);
break;
case T_BIGNUM:
b = rb_big2dbl(y);
break;
case T_FLOAT:
b = RFLOAT(y)->value;
if (isnan(b)) return Qfalse;
break;
default:
return rb_num_coerce_relop(x, y);
}
if (isnan(a)) return Qfalse;
return (a <= b)?Qtrue:Qfalse;
}
I'm not going to describe it in detail,
README.EXT
in Ruby source distribution already does a pretty good job. I just think it's a pretty good language:- It's almost as fast as pure C
- It is far easier to code than pure C, thanks to garbage collection, decent stdlib, and real OO (where real means something based on message-passing, no C++ crap)
- It is far nicer than most similar languages like Perl's XS.
RubyC also offers pretty good performance/expressiveness trade-off - one can code performance-critical sections in C, the glue in RubyC, the high-level stuff in Ruby, and it would all work together well. At least it beats Java.
It's interesting to have a short insight into Ruby C runtime - I like the idea of using a slightly higher-level C to develop applications.
ReplyDeleteI'd also recommend having a look at Lua or Io runtimes, which are easy to use and quite efficient as well.