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?