[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Fixnum <=> confusion

Robert Evans

10/6/2004 7:43:00 AM

Hi,

I am recently learning Ruby, and came across an interesting problem
that I do not understand. I was trying to count how many times the sort
method was called on an object by overridding <=> to count the number
of calls.

I decided to extend Fixnum as follows, but it didn't work. Can anyone
tell me why? Thanks.

Bob Evans


Code:

class Fixnum

@@count = 0

alias originalComparator <=>

def <=>(o)
@@count += 1
originalComparator(o)
end

def Fixnum.count
@@count
end
end

Running against it:

>array = [5, 4, 3, 2, 1]
=> [5,4,3,2,1]

>array.sort
=> [1,2,3,4,5]

>Integer.count
=> 0

Expected => 6 > result > 0

Now, if I call 1<=>2 then count increments. Does this mean that Fixnum
sorting does not call those operators? Thanks for any help.



3 Answers

Yukihiro Matsumoto

10/6/2004 9:22:00 AM

0

Hi,

In message "Re: Fixnum <=> confusion"
on Wed, 6 Oct 2004 16:43:05 +0900, Robert Evans <robert.evans@acm.org> writes:

|Now, if I call 1<=>2 then count increments. Does this mean that Fixnum
|sorting does not call those operators? Thanks for any help.

sort skips <=> calls for fixnums to gain performance.

matz.



Brian Candler

10/6/2004 9:38:00 AM

0

On Wed, Oct 06, 2004 at 04:43:05PM +0900, Robert Evans wrote:
> Now, if I call 1<=>2 then count increments. Does this mean that Fixnum
> sorting does not call those operators? Thanks for any help.

Use The Source, Luke :-)

$ cd /v/build/ruby/ruby-1.8.1-2004.05.02/
$ less array.c

static int
sort_2(ap, bp)
...
if (FIXNUM_P(a) && FIXNUM_P(b)) {
if (a > b) return 1;
if (a < b) return -1;
return 0;
}
if (TYPE(a) == T_STRING && TYPE(b) == T_STRING) {
return rb_str_cmp(a, b);
}
...
static VALUE
sort_internal(ary)
VALUE ary;
{
qsort(RARRAY(ary)->ptr, RARRAY(ary)->len, sizeof(VALUE),
rb_block_given_p()?sort_1:sort_2);
return ary;
}

In other words: Array#sort, when called without a block, special-cases the
comparison of Fixnum to Fixnum and String to String, doing a hard-coded test
instead of calling the spaceship operator.

Try doing:
array.sort { |a,b| a<=>b }
to force it to do the method call.

Regards,

Brian.


Robert Evans

10/6/2004 10:29:00 AM

0

Aha. Thanks for the answer and the friendly reminder about the source.


On Oct 6, 2004, at 2:38 AM, Brian Candler wrote:

> On Wed, Oct 06, 2004 at 04:43:05PM +0900, Robert Evans wrote:
>> Now, if I call 1<=>2 then count increments. Does this mean that Fixnum
>> sorting does not call those operators? Thanks for any help.
>
> Use The Source, Luke :-)
>
> $ cd /v/build/ruby/ruby-1.8.1-2004.05.02/
> $ less array.c
>
> static int
> sort_2(ap, bp)
> ...
> if (FIXNUM_P(a) && FIXNUM_P(b)) {
> if (a > b) return 1;
> if (a < b) return -1;
> return 0;
> }
> if (TYPE(a) == T_STRING && TYPE(b) == T_STRING) {
> return rb_str_cmp(a, b);
> }
> ...
> static VALUE
> sort_internal(ary)
> VALUE ary;
> {
> qsort(RARRAY(ary)->ptr, RARRAY(ary)->len, sizeof(VALUE),
> rb_block_given_p()?sort_1:sort_2);
> return ary;
> }
>
> In other words: Array#sort, when called without a block, special-cases
> the
> comparison of Fixnum to Fixnum and String to String, doing a
> hard-coded test
> instead of calling the spaceship operator.
>
> Try doing:
> array.sort { |a,b| a<=>b }
> to force it to do the method call.
>
> Regards,
>
> Brian.
>