回答:
TL; DR:
シンボルを使用すると、比較を行う際の時間を節約できるだけでなく、一度しか保存されないため、メモリも節約できます。
Rubyシンボルは不変(変更できません)で、何かをはるかに簡単に検索できます
短い(おかしい)答え:
シンボルを使用すると、比較を行う際の時間を節約できるだけでなく、一度しか保存されないため、メモリも節約できます。
Rubyのシンボルは基本的に「不変文字列」です。つまり、変更できないことを意味します。つまり、同じシンボルがソースコード全体で何度も参照された場合、常に同じエンティティとして格納されます。たとえば、同じオブジェクトIDを持ちます。 。
一方、文字列は変更可能であり、いつでも変更できます。これは、Rubyがソースコード全体で言及する各文字列を個別のエンティティに格納する必要があることを意味します。たとえば、ソースコードで複数回言及される文字列「name」がある場合、Rubyはこれらすべてを個別のStringオブジェクトに格納する必要があります。後で変更される可能性があります(これはRuby文字列の性質です)。
文字列をハッシュキーとして使用する場合、Rubyは文字列を評価し、その内容を調べ(そしてそのハッシュ関数を計算し)、その結果を、すでにハッシュに格納されているキーの(ハッシュされた)値と比較する必要があります。 。
シンボルをハッシュキーとして使用する場合、それは不変であることが暗黙的であるため、Rubyは基本的に(のハッシュ関数)オブジェクトIDを、すでに格納されているキーの(ハッシュされた)オブジェクトIDと比較することができます。ハッシュ。(はるかに高速)
欠点: 各シンボルは、Rubyインタープリターのシンボルテーブルのスロットを消費します。これは解放されません。シンボルがガベージコレクションされることはありません。したがって、コーナーケースは、多数のシンボル(たとえば、自動生成されたもの)がある場合です。その場合は、これがRubyインタープリターのサイズにどのように影響するかを評価する必要があります。
ノート:
文字列比較を行う場合、RubyはオブジェクトIDだけでシンボルを比較できます。評価する必要はありません。これは、評価が必要な文字列を比較するよりもはるかに高速です。
ハッシュにアクセスすると、Rubyは常にハッシュ関数を適用して、使用するキーから「ハッシュキー」を計算します。MD5ハッシュのようなものを想像できます。そして、Rubyはそれらの「ハッシュされたキー」を互いに比較します。
長い答え:
その理由は効率であり、文字列に対して複数の利点があります。
O(n)
文字列用であり、シンボル用の定数です。さらに、Ruby 1.9は記号キー(例:)を使用したハッシュのために単純化された構文を導入し、h.merge(foo: 42, bar: 6)
Ruby 2.0には記号キーに対してのみ機能するキーワード引数があります。
注:
1)RubyがString
キーを他のタイプとは異なる方法で処理することを知って驚くかもしれません。確かに:
s = "foo"
h = {}
h[s] = "bar"
s.upcase!
h.rehash # must be called whenever a key changes!
h[s] # => nil, not "bar"
h.keys
h.keys.first.upcase! # => TypeError: can't modify frozen string
文字列キーの場合のみ、Rubyはオブジェクト自体ではなく凍結されたコピーを使用します。
2)「b」、「a」、および「r」の文字:bar
は、プログラム内のすべての出現に対して一度だけ格納されます。Ruby 2.2より前のバージョンSymbols
では、グローバルシンボルルックアップテーブルに永遠に残るため、再利用されないものを常に作成することは悪い考えでした。Ruby 2.2はそれらをガベージコレクションするので、心配ありません。
3)実際、Ruby 1.8.xでは、オブジェクトIDが直接使用されるため、シンボルのハッシュの計算に時間がかかりませんでした。
:bar.object_id == :bar.hash # => true in Ruby 1.8.7
Ruby 1.9.xでは、ハッシュが1つのセッションから別のセッション(のハッシュを含むSymbols
)に変更されると、これが変更されました。
:bar.hash # => some number that will be different next time Ruby 1.9 is ran
再:文字列を使用するよりも利点は何ですか?
(非常に)シンボルをハッシュすることは、整数をハッシュすることと文字列をハッシュすることと同じであるため、値の検索がわずかに速くなります。
短所:プログラムのシンボルテーブルで、解放されないスロットを消費します。