Andre Nathan
12/30/2007 3:11:00 AM
On Sun, 2007-12-30 at 11:36 +0900, Andre Nathan wrote:
> On Sun, 2007-12-30 at 10:59 +0900, KUBO Takehiro wrote:
> > Use rb_ary_sort_bang instead of call_sort_bang.
> > I don't know why call_sort_bang doesn't work.
>
> Thanks! For some reason I thought rb_ary_sort_bang was static while it
> isn't...
Actually...
I was using rb_funcall() because this way "sort!" understands it's being
given a block, while when calling rb_ary_sort_block() directly it
doesnt:
static VALUE
sort_by_length(VALUE ary)
{
long v0 = RARRAY_LEN(RARRAY_PTR(ary)[0]);
long v1 = RARRAY_LEN(RARRAY_PTR(ary)[1]);
return LONG2FIX(v0 - v1);
}
static VALUE
foo(void)
{
VALUE a = rb_ary_new();
rb_ary_push(a, rb_ary_new3(2, INT2FIX(3), INT2FIX(3)));
rb_ary_push(a, rb_ary_new3(1, INT2FIX(2)));
rb_ary_push(a, rb_ary_new3(3, INT2FIX(0), INT2FIX(0), INT2FIX(0)));
rb_iterate(rb_ary_sort_bang, a, sort_by_length, 0);
rb_funcall(rb_mKernel, rb_intern("p"), 1, a);
return a;
}
This prints "[[0, 0, 0], [2], [3, 3]]" and not "[[2], [3,3], [0, 0, 0]]"
as expected. sort_by_length() is never called, and the sub-arrays were
sorted by their contents, because rb_block_given_p() returns false in
rb_ary_sort_bang().
I also tried
rb_block_call(a, rb_intern("sort!"), 0, 0, sort_by_length, 0);
but that has the same problem I had with rb_funcall -- sort_by_length is
given the current array element only as its argument.
Andre