From: Andre Nathan Date: 2007-12-30T12:11:03+09:00 Subject: Re: Using "sort!" in a C extension (1.9 problem) 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