バックエンド

【Ruby】ハッシュとシンボルについて 省略記法やシンボルと文字列の違い

reisuta

Webエンジニア | 20代中盤 | 大学時代はGmailすら知らないIT音痴でプログラミングとは無縁の生活を送る → 独学でプログラミングを学ぶ → Web系受託開発企業にエンジニアとして就職 → Web系自社サービス企業に転職 | 実務未経験の頃からVimを愛好しており、仕事でもプライベートでも開発はVimとTmuxを使っているので、VSCodeに疎いのが最近の悩み。何だかんだでやっぱりRubyが好き。

本記事では、Rubyの文法の中でも特徴的な、
ハッシュとシンボルについて紹介します。

特にシンボルについては、他のプログラミング言語では、
あまり見かけないデータ構造かと思います。

こうしたハッシュとシンボルについての解説と、文字列との違い、
省略記法についても言及します。

本記事の動画は下記になります。

ハッシュ

ハッシュというと、
なんぞやって感じる人が多いと思いますが、
これは要するに、他のプログラミング言語で言う、
辞書とか連想配列みたいなもんで、
{'taro' => 100, 'hanako' => 200}みたいなデータ構造です。

irb(main):001:0> money = {'taro' => 100, 'hanako' => 200}
=> {"taro"=>100, "hanako"=>200}
irb(main):002:0> money
=> {"taro"=>100, "hanako"=>200}

ハッシュもブロックも、
同じ{}で定義するので紛らわしいですね。

要素の取得/追加/変更

要素の追加などは、
配列のときと似ており、

irb(main):004:0> money['takumi'] = 400 #これで追加
=> 400
irb(main):005:0> money
=> {"taro"=>100, "hanako"=>200, "takumi"=>400}
irb(main):006:0> money['taro'] #取得したいキーを指定する
=> 100
irb(main):007:0> money['kyoko'] #存在しないキーならnilを返す
=> nil

といった感じです。

Rubyの配列についての解説は、
こちらの記事をご参考ください。

Ruby配列ループ
参考【Rubyループ処理】 配列each/map/forやスコープ

本記事では、Rubyの配列とループ処理を扱います。 Rubyには、ブロックという特徴的な文法があり、ループ処理もそれに関連してか、他のプログラミング言語よりもメソッドがたくさんあります。 本記事ではそ ...

続きを見る

キーにシンボルを使う

キーに文字列ではなく、
シンボル(シンボルについては後述)
を使うことのほうがおそらく多いので、
それについても紹介します。

irb(main):026:0> money = { :taro => 100, :hanako => 200 }
=> {:taro=>100, :hanako=>200}
irb(main):027:0> money[:taro]
=> 100

キーがシンボルの場合は、
省略形もあります。

irb(main):028:0> money = { taro: 100, hanako: 200 }
=> {:taro=>100, :hanako=>200}
irb(main):029:0> money
=> {:taro=>100, :hanako=>200}
irb(main):030:0>

=> を使わないで、
シンボル: 値という省略した記法が使えます。

そして、おそらくこの省略された記法が
一番良く使われているかと思います。

メソッド呼び出し時の省略

メソッドの引数の最後がハッシュの場合、
{}を省略できます。

# Railsで見かける例のやつ
stylesheet_link_tag 'application', { media: 'all',
                                     'data-turbolinks-track': 'reload' }
# 上は以下のように書いても同じ
stylesheet_link_tag 'application', media: 'all',
                                   'data-turbolinks-track': 'reload'

def print_hello(greet, options)
  puts options
  puts greet
end

print_hello('hello', { taro: 100, hanako: 200})
print_hello 'hello', { taro: 100, hanako: 200} #メソッド呼び出しの()は省略できる
print_hello 'hello', taro: 100, hanako: 200 #ハッシュが最後の引数なので{}は省略できる

 Rubyは何をするにも
省略記法があるので、
Dryすぎて、逆に混乱してしまうのが悩みです。

シンボル

さて、ハッシュの次は、
シンボルについて触れていきます。

シンボルは、結構Ruby独特のものかなと感じており、
他のプログラミング言語ではあまり見たことがないかもしれません。

class Symbol (Ruby 3.2 リファレンスマニュアル) (ruby-lang.org)

平たく言えば、文字列と似ているものですが、
文字列とも異なるといった感じです。
:hogeのように表します。

irb(main):009:0> :hoge
=> :hoge
irb(main):010:0> :hoge.class
=> Symbol
irb(main):011:0> 'hoge'.class
=> String

シンボルと文字列の違い

そもそもシンボルは、文字列っぽいですが、
内部では整数として扱われているようです。

シンボルは、ソース上では文字列のように見え、内部では整数として扱われる、両者を仲立ちするような存在です。

名前を管理するという役割上、シンボルと文字列は一対一に対応します。また、文字列と違い、immutable (変更不可)であり、同値ならば必ず同一です。

Ruby 3.2 リファレンスマニュアル

そのため、文字列よりも高速に比較ができるようです。

加えて、シンボルは同じものなら、
同じオブジェクトという特徴があります。

irb(main):012:0> :hoge.object_id
=> 2039708
irb(main):013:0> :hoge.object_id
=> 2039708
irb(main):014:0> :hoge.object_id
=> 2039708
irb(main):015:0> 'hoge'.object_id
=> 180
irb(main):016:0> 'hoge'.object_id
=> 200
irb(main):017:0> 'hoge'.object_id
=> 220

あとは、上記のリファレンスマニュアルにもあったように、
immutable(変更不可)なので、破壊的メソッドなどで書き換えられてしまうという
懸念がないのがメリットかもしれません。

irb(main):018:0> a = 'hoge'
=> "hoge"
irb(main):019:0> b = :hoge
=> :hoge
irb(main):020:0> a.upcase!
=> "HOGE"
irb(main):021:0> a #破壊的メソッドによって書き換わっている
=> "HOGE"
irb(main):022:0> b.upcase! #破壊的メソッドは呼び出せない
Traceback (most recent call last):
        4: from /Users/reisuta/.rbenv/versions/2.7.7/bin/irb:23:in `<main>'
        3: from /Users/reisuta/.rbenv/versions/2.7.7/bin/irb:23:in `load'
        2: from /Users/reisuta/.rbenv/versions/2.7.7/lib/ruby/gems/2.7.0/gems/irb-1.2.6/exe/irb:11:in `<top (required)>'
        1: from (irb):22
NoMethodError (undefined method `upcase!' for :hoge:Symbol)
Did you mean?  upcase

 もちろん、ケースバイケースではあるのですが、
個人的には文字列とシンボルで迷ったら、
可能な限りシンボルを使ったおくのが好ましいのかなと感じます。

シンボルは、シンプルなようで、
意外と奥が深いので使いこなすのは、
案外難しい印象です。

少しづつ慣れて、使いこなせるようになりたいですね。

  • この記事を書いた人
  • 最新記事

reisuta

Webエンジニア | 20代中盤 | 大学時代はGmailすら知らないIT音痴でプログラミングとは無縁の生活を送る → 独学でプログラミングを学ぶ → Web系受託開発企業にエンジニアとして就職 → Web系自社サービス企業に転職 | 実務未経験の頃からVimを愛好しており、仕事でもプライベートでも開発はVimとTmuxを使っているので、VSCodeに疎いのが最近の悩み。何だかんだでやっぱりRubyが好き。

おすすめ記事はこちら

Vim/Neovimプラグイン 1

プラグインをどれだけ入れるかは、その人の思想なども関係するので、一概にこれがいいというのはないかもしれません。 プラグインを全く入れない人もいれば、100個以上入れる人もいます。 ただそれでも、これだ ...

VimとNeovimの比較 2

本記事では、VimとNeovimの違いについて、解説します。 VimとNeovimの違いについては、普段頻繁にVimなどを使う方でなければ、正直、あまり気にしなくてもいいかなと思います。 ただ、Vim ...

Ruby変数やすべてがオブジェクトについて 3

本記事は、Rubyの基礎文法である、変数や真偽値、論理演算子に触れると同時に、「すべてがオブジェクト」というRubyの特徴的な思想についても解説します。 この思想は、Rubyの文法の根幹になっているの ...

4

エンジニアにおすすめの技術書 書籍学習は、エンジニアの嗜みみたいなところがありますが、 良書というものは、意外とそこまで多くもありません。 そこで本記事では「技術書マニアの筆者が厳選した技術書20選」 ...

5

エンジニアになるには? プログラミングは、専門性が高く自分一人で勉強するのが大変に感じることも多いですよね。 そこで本記事では「おすすめのプログラミングスクール5選」を特徴と、現役エンジニア目線で優れ ...

-バックエンド