🤔

Ruby初学者が困るシンボル「:」を簡単に理解する

2023/01/22に公開約1,800字2件のコメント

Railsチュートリアル進めてるけど シンボル「:」 ってなんぞ?


と思った方はいないでしょうか。
といっても「シンボルでしょ? ハッシュを簡単に表記するのに使うよね」くらいは知ってる方も多いでしょうし、私もそのような認識でした。しかしチュートリアルを進めていると、「:」の出現頻度が高くモヤモヤすることが多くなってきませんか?
そこで少し踏み込んで理解しようと思い学習しましたので、私と同じ初学者の参考になればと思います。

シンボルの定義

リファレンスでは次のとおり説明されています。※一部抜粋

シンボルは任意の文字列と一対一に対応するオブジェクトです。
文字列の代わりに用いることもできますが、必ずしも文字列と同じ振る舞いをするわけではありません。同じ内容のシンボルはかならず同一のオブジェクトです。

なんとなくわかる。深掘りしてみましょう。

シンボルと文字列の違い

- クラス

シンボルと文字列の違いを見てみましょう。

#文字列
a = "ruby" 
a.class # => String

#シンボル
b = :rails 
b.class # => Symbol

上記のコードから文字列はStringクラスに属しているのに対し、シンボルはSymbolクラスに属していることがわかります。元となるクラスが異なることがわかりました。

- id

※出力idはサンプルです

#文字列
'ruby'.object_id # => 1234567890123
'ruby'.object_id # => 3210987654321

#シンボル
:rails.object_id # => 1111111
:rails.object_id # => 1111111

上記のコードから同じ文字列であっても、文字列は生成される度に異なるidとなるのに対し、
シンボルでは都度同じidとなっています。
このことから、同じ文字を使用するならシンボルを用いた方がメモリ効率が良くなることがわかります。

余談ですが、シンボルは見た目が文字列でもRuby内部的には整数値で管理されているようです。コンピュータ的には数値の方が扱いやすいため、見た目上同じ文字でもシンボルの方がより高速に処理できることとなります。

また、シンボルにはイミュータブルな性質を兼ね備えています。イミュータブルとは、破壊的な変更ができない、つまり一度生成されたシンボルは変更することができないという意味です。

シンボルの活用

- ハッシュのキーと値

ハッシュのキーと値にはシンボルを用いることができます。

#キーに使用する
language = { :JavaScript => 'js', :Ruby => 'rb'}

#キーにシンボルを用いる場合は上記コードを簡略化できる
language = { JavaScript: 'js', Ruby:'rb' }

ここで覚えておきたいのが、キーも値もシンボルで上記で説明したハッシュの簡略表記を用いる場合下記のようなコードになるということです。

#キーにも値にも使用する
language = { :JavaScript => :js, :Ruby => :rb}

#上記コードを簡略化
language = { JavaScript: :js, Ruby: :rb }

シンボル表記が「: :」と続いていて違和感がありますが、キーも値もシンボルを用いた場合上記のようなコードになります。これを知っていると少しはRubyコードに抵抗がなくなるのではないかと思っています。

まとめ

・シンボルはメモリ効率がよく処理速度も速い
・一度生成されたシンボルは変更できない(ある意味安全)
・省略表記を覚えておくとコードが読みやすくなる

終わりに

ここまで読んで頂きありがとうございました。間違っていることや捕捉事項があればコメントやTwitter(@hiro)に遠慮なくご指摘頂ければと思います。フロントエンドエンジニアになりたいのに最近バックエンドの方が多く勉強しているの良くないよね🤔

Discussion

hiro_xreさん、こんにちは。
この記事のサンプルコードですが、irbにコピペすると文法エラーが発生します。

$ irb   
irb(main):001:0> language = { JavaScript : : js, Ruby : : rb }
/Users/jnito/.rbenv/versions/3.2.0/lib/ruby/3.2.0/irb/workspace.rb:119:in `eval': (irb):1: syntax error, unexpected ':', expecting => (SyntaxError)
language = { JavaScript : : js, Ruby : : rb }
                        ^

	from /Users/jnito/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/irb-1.6.2/exe/irb:11:in `<top (required)>'
	from /Users/jnito/.rbenv/versions/3.2.0/bin/irb:25:in `load'
	from /Users/jnito/.rbenv/versions/3.2.0/bin/irb:25:in `<main>'
irb(main):002:0> language = { JavaScript : 'js', Ruby : 'rb'}
/Users/jnito/.rbenv/versions/3.2.0/lib/ruby/3.2.0/irb/workspace.rb:119:in `eval': (irb):2: syntax error, unexpected ':', expecting => (SyntaxError)
language = { JavaScript : 'js', Ruby : 'rb'}
                        ^

	from /Users/jnito/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/irb-1.6.2/exe/irb:11:in `<top (required)>'
	from /Users/jnito/.rbenv/versions/3.2.0/bin/irb:25:in `load'
	from /Users/jnito/.rbenv/versions/3.2.0/bin/irb:25:in `<main>'

もう一度本文中のコードを見直すことをお勧めします。

参考 「よいサンプルコード」ってどんなサンプルコード? 〜Qiitaや技術ブログを書くときに気を付けること〜 - Qiita

Junichi Itoさま
コメント頂きありがとうございます。
ご指摘の内容について修正させて頂きました。
インデント管理など気をつけたいと思います!
ご指摘ありがとうございました🙇‍♂️

ログインするとコメントできます