1

Symbol#<=>

簡単に言うと、各シンボルでto_sを呼び出した後、シンボルをother_symbolと比較します。シンボルがother_symbolより小さいか、等しいか、大きいかに応じて、-1、0、+ 1、またはnilを返します。nil2つの値が比較できない場合に返されます。

Symbol#<=>私は戻ったときにどのように機能するかを理解しようとしていましたnil。そうすることで、私はコードで遊んだ:

>> :x.to_s
=> "x"
>> 'x'.to_s
=> "x"

上記のIRBコードから、戻り値はになると思いました0。しかし、実際はnilです。docが言うように、<=>演算子を使用する前に、とto_sの両方が適用されます。しかし、ここでは、以下のコードはその原則をサポートしていないようです。RHOLHO

>> :x <=> "x"
#=> nil

だから私は自分自身に答えるためにソースコードを見ようとしました:

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));
}

ソースコードを見ると、RHOがクラスのオブジェクトでない場合はSymbolnilが返されることは明らかです。IRBでもっと何かを見てみましょう:

>> "x" <=> :x
#=> nil

再びnilrb_str_cmp_m(rb_sym_to_s(sym),rb_sym_to_s(other))これから実行されるというソースコード。だから今、私はのソースコードを見に行きましたSTRING.C。したがって、基本的にはを一時停止していrb_str_cmp_m(???,"x")ます。今私はgithubから見つけました:(?はどの値がわからないことを意味します)

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);
}

しかし、上記のコードは理解できませんでしたが、クラスのオブジェクトではないnil場合にどのように生成するかという答えがあると思います。LHOSymbol

誰かがここで私を助けて、そうでないnilときにどのように来るのかを理解できますか?LHOsym

4

1 に答える 1

3

SymbolとStringは異なるタイプであるため、FixnumとTrueClassが比較できないのと同様に、比較できません。シンボルがフリーズされた文字列ではないのはなぜですか?を参照してください。それらが実際にどのように同じである必要があるかについての怒りつまり、クラスSymbolをクラスStringから継承させる場合)。

最初の例では、メソッド<=>はシンボルで呼び出されており、引数は文字列であるため、sym_cmpnilを返します。

2番目の例では、メソッド<=>は文字列で呼び出されており、引数はシンボルです。したがって、;rb_check_funcallを使用して文字列に自然に変換できるかどうかを確認します。to_strそれはできません( "NoMethodError:undefined method to_strfor:bar:Symbol")ので、その場合も(最終的に)nil返されます。(掘り下げてrb_invcmp、「最終的に」そこに肉付けするために何ができるかを確認する必要があります:-))

于 2013-03-17T12:28:37.400 に答える