【Ruby】シンボルの書き方と使い方の基本
開発環境
- Ruby version: ruby 3.1.2
Rubyのシンボルとは
Rubyのシンボルとは、任意の文字列と一対一に対応するシンボルクラスのオブジェクトです。 シンボルはソース上では文字列のように見えますが、Rubyの内部では「整数」として管理されているため、immutable (変更不可)なオブジェクトで同値ならば必ず同一となります。 公式リファレンス:https://docs.ruby-lang.org/ja/latest/class/Symbol.html
Rubyのシンボルの書き方
Rubyのシンボルの書き方をご紹介します。
1"symbol" #文字列 2:symbol #シンボル
文字列は「'(シングルクォート)」、または「"(ダブルクォート)」で囲みますが、シンボルは「:(コロン)」から始まります。
Rubyのシンボルの使い方
Rubyのシンボルのよくあるパターンをサンプルコードを用いて使い方の解説をしていきます。
配列でシンボルを使うパターン
配列でシンボルを使うパターンです。
1# 配列でstringクラスを使用する場合 2string_array = ["obj1", "obj2", "obj3", "obj4", "obj5"] 3p string_array[0] # "obj1" 4 5# 配列でsymbolクラスを使用する場合 6symbol_array = [:obj1, :obj2, :obj3, :obj4, :obj5] 7p symbol_array[0] # :obj1
取り出される値はそれぞれstringクラスとsymbolクラスになります。
ハッシュでシンボルを使うパターン
ハッシュでシンボルを使うパターンです。
1# ハッシュでstringクラスを使用する場合 2string_hash = { "key1" => "value1", "key2" => "value2", "key3" => "value3" } 3p string_hash["key1"]
ハッシュのキーにstringクラスを使用している場合、値を取り出すときのキー指定もstringクラスを使用します。
1# ハッシュでsymbolクラスを使用する場合(キーが前置コロン) 2symbol_hash1 = { :key1 => :value1, :key2 => :value2, :key3 => :value3 } 3p symbol_hash1[:key1]
ハッシュのキーに前置コロンのsymbolクラスを使用している場合、値を取り出すときのキー指定も前置コロンのsymbolクラスを使用します。
1# ハッシュでsymbolクラスを使用する場合(キーが後置コロン) 2symbol_hash2 = { key1: :value1, key2: :value2, key3: :value3 } 3p symbol_hash2[:key1]
ハッシュのキーに後置コロンを使用した場合は「=>(ダブルアロー)」を省略して記述しますが、値を取り出すときのキー指定は前置コロンのsymbolクラスを使用します。
Rubyのシンボルと文字列の違い
Rubyのシンボルと文字列の違いは大きく4つあります。
シンボルと文字列のクラスの違い
シンボルはSymbolクラスとなり、文字列はStringクラスとなります。
1p "symbol".class # String 2p :symbol.class # Symbol
シンボルと文字列の破壊的な変更の違い
文字列は破壊的な変更は可能ですが、シンボルは破壊的な変更は不可能です。
1# 文字列は破壊的な変更は可能 2string = "ruby" 3p string.upcase! # "RUBY" 4 5# シンボルは破壊的な変更は不可能 6symbol = :ruby 7p symbol.upcase! # undefined method `upcase!' for :ruby:Symbol
シンボルと文字列のオブジェクトの違い
シンボルは同じ内容であれば必ず同一オブジェクトとなりますが、文字列は同じ内容であっても同一のオブジェクトにはなりません。
1p :ruby.object_id #=> 727388 2p :ruby.object_id #=> 727388 3 4p "ruby".object_id #=> 60 5p "ruby".object_id #=> 80
シンボルは同一のオブジェクトになるため、メモリの使用効率が良いということになります。
シンボルと文字列の処理速度の違い
シンボルは内部で整数として管理されるため、文字列と比べて高速に処理できます。
1require 'benchmark' 2include Benchmark 3 4# シンボルを使ったメソッド 5def processing_speed_symbol(num) 6 obj1 = :ruby 7 obj2 = :ruby 8 num.times do 9 obj1 == obj2 10 end 11end 12 13# 文字列を使ったメソッド 14def processing_speed_string(num) 15 obj1 = "ruby" 16 obj2 = "ruby" 17 num.times do 18 obj1 == obj2 19 end 20end 21 22# 計測結果のメソッド 23Benchmark.benchmark(CAPTION, 7, FORMAT) do |x| 24 x.report("symbol"){ processing_speed_symbol(1000000) } 25 x.report("string"){ processing_speed_string(1000000) } 26end
上記はobj1とobj2を比較する処理にシンボルを使った場合と文字列を使った場合のメソッドです。 そして、下記が実行結果です。
1user system total real 2symbol 0.031000 0.000000 0.031000 ( 0.039583) 3string 0.047000 0.000000 0.047000 ( 0.041310)
文字列よりシンボルのほうが処理速度が速いことがわかったかと思います。
おわりに
Rubyのシンボルの使い方を解説してきました。 シンボルはsymbolクラス、文字列はstringクラスになるため、オブジェクトのクラスが異なれば使用できるメソッドも違います。 特に連想配列であるハッシュでは必ずと言ってよいほどシンボルを使用するため、最低でも前置コロンと後置コロンの使い方は知っておきましょう。