QA@IT

RubyのHashのキーはシンボルにするべき?

5745 PV

現在 ruby 1.9.3でプログラミングしているのですが、Hashのキーをシンボルで書くのか、Stringで書くのか悩んでいます。

自分のシンボルの理解はちゃんとしてないのですが、自分の考えではシンボルは固定的な文字を使いたいときに使う物だ考えています。逆に言うとStringはよく変更される物となります。

なので、Hashのキーはシンボルを使って書いていたのですが、他のライブラリ等を使っているとHashのKeyをStringで返してくるものがあることにきづきました。
これだと、キーをシンボルで指定してValueを取っていた場合、バグになってしまいます(nilを返す)。

ここで疑問なのはRubyのHashのキーはシンボルとString、どっちが一般的なんですか?
ご回答いただけるとうれしいです。

回答

Ruby 1.9.xでとても書きやすい記法が導入されたりすることもあり、多くの場合はSymbolを使っていいんじゃないでしょうか。

一般的かどうかについて、私感ではRailsが盛り上がってきた2006年ごろ以降に作られたライブラリは、Symbolをよく使っているような気がします。before Railsだと半々くらいでしょうか。

また、RailsというかActiveSupportではHashWithIndifferentAccessという、文字列でもシンボルでもアクセス可能なHashのサブクラスが多用されています。もし「これから」「自分が」「ActiveSupport前提でのライブラリ」を作るのであれば、こちらを使うのがユーザのために一番良さそうです。なお、https://github.com/intridea/hashie など、おなじような「ちょっと便利なHash」は他にも幾つかあります。

蛇足ですが、明確な注意点としては「外部からの入力のパース結果」をSymbolをキーとしたHashで持つとヤバイことになる可能性が上がります。SymbolにしてしまうとGCされないので,
適当なキーをもつ入力を繰り返すとメモリを浪費させることができそうです。
このあたりを考慮したのか、前述のHashWithIndifferentAccessのキーはStringにしており、hash[:foo]などで問い合わせる際にStringあわせて扱っているようですね。

編集 履歴 (0)
  • なるほど、基本的にはSymbolを使うという感じですね。あとSymbolはGCの対象にならないのは知らなかったです。色々勉強になりました、ありがとうございます。 -

この件に関して、こちらのブログが参考になると思います。

コメント部分も参照。

個人的には、

  • キーの種類が固定されいていて数が限られている(すべてソースコード上にある) → シンボル
  • キーの種類が不定(ユーザ入力や外部のデータがキーになる)→ 文字列

かなぁ。

編集 履歴 (0)
  • 使い分けの方針はsawat1203さんの見解が良いと思います。
    理由はリンク先にある通り、シンボルはGCされないからですね。
    -
  • リンクありがとうございます。勉強になりました。
    自分も、Hashのキーは使い分けていこうと思います。
    -

どちらが一般的かは知らないのですが、Ruby1.9.3 だと以下のようになることは把握しておいた方がよいと思います。

{:k => "v"}        # => {:k=>"v"}
{"k" => "v"}       # => {"k"=>"v"}
{k: "v"}           # => {:k=>"v"}
{"k": "v"}         # => 
 # ~> -:4: syntax error, unexpected ':', expecting tASSOC
 # ~> ...355233619_19807_682768 = ({"k": "v"}          );$stderr.puts...
 # ~> ...                               ^
 # ~> -:4: syntax error, unexpected '}', expecting ')'
 # ~> ...3619_19807_682768 = ({"k": "v"}          );$stderr.puts("!XM...
 # ~> ...                               ^
 # ~> -:4: syntax error, unexpected $end, expecting ')'
編集 履歴 (0)
  • お返事ありがとうございます。すいません、回答の意図がうまくつかめていないのですが、つまり:でも値を分ける事ができるということですか? -
  • キーを文字列にした場合、「キーワード引数のようなハッシュ記法」で書けないみたいなのです。 -
  • なるほど、キーワード引数を理解していませんでした。このような書き方が出来るのですね。そしてそれは文字列ではできないと。勉強になりました、ありがとうございます。 -
ウォッチ

この質問への回答やコメントをメールでお知らせします。