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