LoginSignup
1
0

More than 1 year has passed since last update.

RubyのSymbol(シンボル)とは?文字列とは何が違うのか

Posted at

Rubyでは全ての値はオブジェクトのため、一見ただの数値に見えてもそれはIntegerクラスのオブジェクトです。
そこでmethodsメソッドを使って、そのオブジェクトが所属するIntegerクラスのメソッドを見てみたいと思います。

irb
irb(main):006:0> 123.class
=> Integer
irb(main):007:0> 123.methods
=> [:-@, :**, :<=>, :upto, :<<, :<=, :>=, :==, :chr, :===, :>>, :[], :%, :&, :inspect, :*, :+, :ord, :-, :/, :size, :succ, :<, :>, :to_int, :coerce, :to_s, :to_i, :to_f, :divmod, :to_r, :fdiv, :modulo, :remainder, :abs, :magnitude, :integer?, :floor, :ceil, :round, :truncate, :^, :odd?, :even?, :allbits?, :anybits?, :nobits?, :downto, :times, :pred, :pow, :bit_length, :digits, :numerator, :denominator, :rationalize, :gcd, :lcm, :gcdlcm, :next, :div, :|, :~, :abs2, :angle, :+@, :conjugate, :to_c, :conj, :phase, :rect, :polar, :eql?, :singleton_method_added, :i, :real?, :zero?, :nonzero?, :finite?, :infinite?, :step, :positive?, :negative?, :clone, :dup, :arg, :quo, :rectangular, :real, :imaginary, :imag, :between?, :clamp, :instance_variable_defined?, :remove_instance_variable, :instance_of?, :kind_of?, :is_a?, :tap, :instance_variable_get, :instance_variable_set, :instance_variables, :protected_methods, :private_methods, :public_send, :method, :public_method, :singleton_method, :define_singleton_method, :extend, :to_enum, :enum_for, :=~, :!~, :respond_to?, :freeze, :object_id, :send, :display, :class, :nil?, :hash, :singleton_class, :then, :itself, :yield_self, :untaint, :taint, :tainted?, :trust, :untrust, :untrusted?, :singleton_methods, :frozen?, :methods, :public_methods, :equal?, :!, :instance_exec, :!=, :instance_eval, :__id__, :__send__]

このとき、メソッド名が「:(コロン)」が付いて始まっています。
これがSymbol(シンボル)なのですが、それって一体何なのでしょうか。

Symbolとは

Ruby3.0リファレンスマニュアルで調べてみました。

シンボルの実装
Rubyの内部実装では、メソッド名や変数名、定数名、クラス名などの名前を整数で管理しています。
そしてその整数をRubyのコード上で表現したものがシンボルです。

ここで「へぇ~」と思ったのが名前を整数で管理しているという点です。
なぜそんなことをしているのでしょうか。名前なんだから文字列で管理すれば良いのでは…?
答えは書いてありました。

これは名前を直接文字列として処理するよりも速度面で有利だからです。

ふむふむ、どうやらSymbolを使った方が処理が速いようです。

文字列とシンボルの速度を比較してみた

百聞は一見に如かずなので、実際にやってみたいと思います。
速度の判定にはBenchmark-ipsというRubyGemを使ってみます。
【参考】Rubyの処理速度を確認したい時に使うGem【Benchmark-ips】

measure.rb
# 文字列とシンボルの速度を比較するクラス
require 'benchmark/ips'
class Measure
  Benchmark.ips do |x|
    x.report("String"){
      hash = {}
      (1..1000).each do |n|
        hash.store(n, "abc")
      end
    }
    x.report("Symbol"){
      hash = {}
      (1..1000).each do |n|
        hash.store(n, :abc)
      end
    }
    x.compare!
  end
end
処理結果
Warming up --------------------------------------
              String     1.027k i/100ms
              Symbol     1.301k i/100ms
Calculating -------------------------------------
              String     10.815k (± 3.8%) i/s -     54.431k in   5.041519s
              Symbol     13.327k (± 3.5%) i/s -     67.652k in   5.082751s

Comparison:
              Symbol:    13327.4 i/s
              String:    10815.3 i/s - 1.23x  (± 0.00) slower

確かに!リファレンスに書かれている通り、Symbolのほうが速い結果となりました。
HashオブジェクトのvalueもSymbolにしたほうがより早く処理できそうということが分かりました。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0