Symbol#<=> →
simply says: Compares symbol with other_symbol after calling to_s on
each of the symbols. Returns -1, 0, +1 or nil depending on whether
symbol is less than, equal to, or greater than other_symbol. nil
is
returned if the two values are incomparable.
I was trying to understand how Symbol#<=>
works when returning nil
.
Doing so I played with the code:
>> :x.to_s
=> "x"
>> 'x'.to_s
=> "x"
From the above IRB
code I thought the return value will be 0
. But
the actual is nil
. As doc says that before using <=>
operator to_s
is applied both the RHO
and LHO
. But here the below code is not
supporting that principle, seems to me.
>> :x <=> "x"
#=> nil
So I tried to see the source code,to answer myself:
static VALUE
sym_cmp(VALUE sym, VALUE other)
{
if (!SYMBOL_P(other)) {
return Qnil;
}
return rb_str_cmp_m(rb_sym_to_s(sym), rb_sym_to_s(other));
}
Looking at the source code it is clear that if RHO
is not the object
of class Symbol
, nil
will be returned. Let’s see the something
more in IRB:
>> "x" <=> :x
#=> nil
Again nil
. The source code saying that
rb_str_cmp_m(rb_sym_to_s(sym),rb_sym_to_s(other))
will be executed
now. So now I went to the see the source code of STRING.C
->(https://github.com/ruby/ruby/blob/trunk/string.c). So we are
basically pasing the rb_str_cmp_m(???,"x")
. Now the I found from
github:(?
means don’t know what value)
rb_str_cmp_m(VALUE str1, VALUE str2)
{
int result;
if (!RB_TYPE_P(str2, T_STRING)) {
VALUE tmp = rb_check_funcall(str2, rb_intern("to_str"), 0, 0);
if (RB_TYPE_P(tmp, T_STRING)) {
result = rb_str_cmp(str1, tmp);
}
else {
return rb_invcmp(str1, str2);
}
}
else {
result = rb_str_cmp(str1, str2);
}
return INT2FIX(result);
}
But the above code I couldn’t understand.But I beleieve it has the
answer how nil
is producing when LHO
is not the object of class
Symbol
.
Can anyone help me here to understand how the nil
is coming when LHO
is not sym
?