web-dev-qa-db-ja.com

Rubyのコロン演算子とは何ですか?

{ :bla => 1, :bloop => 2 }と言うとき、:は正確に何をしますか?私はどこか文字列に似ているが、どういうわけか記号について読んだ。

私はコンセプトについてあまり明確ではありませんが、誰かが私を啓発できますか?

219
LuxuryMode

:fooは「foo」という名前のシンボルです。シンボルには、同じ名前の2つのシンボルが同一であるという明確な機能があります。

"foo".equal? "foo"  # false
:foo.equal? :foo    # true

これにより、2つのシンボルの比較が非常に高速になります(文字列のようにすべての文字を比較するのではなく、ポインターの比較のみが関係するため)。また、同じシンボルのコピーが無数にありません。

また、文字列とは異なり、シンボルは不変です。

239

答えで言及されていることのいくつかを示すためだけに

require 'benchmark'

n = 1_000_000

print '"foo".equal? "foo" -> ', ("foo".equal? "foo"), "\n"
print '"foo" == "foo"     -> ', ("foo" == "foo"    ), "\n"
print ':foo.equal? :foo   -> ', (:foo.equal? :foo  ), "\n"
print ':foo == :foo       -> ', (:foo == :foo      ), "\n"

Benchmark.bm(10) do |b|
  b.report('string')     { n.times { "foo".equal? "foo" }}
  b.report('str == str') { n.times { "foo" == "foo"     }}
  b.report('symbol')     { n.times { :foo.equal? :foo   }}
  b.report('sym == sym') { n.times { :foo == :foo       }}
end

それを実行すると出力:

"foo".equal? "foo" -> false
"foo" == "foo"     -> true
:foo.equal? :foo   -> true
:foo == :foo       -> true

したがって、equal?を使用して文字列を文字列と比較すると、それらは同じコンテンツであっても異なるオブジェクトであるため失敗します。 ==はコンテンツを比較し、シンボルを使用した同等のチェックははるかに高速です。

                 user     system      total        real
string       0.370000   0.000000   0.370000 (  0.371700)
str == str   0.330000   0.000000   0.330000 (  0.326368)
symbol       0.170000   0.000000   0.170000 (  0.174641)
sym == sym   0.180000   0.000000   0.180000 (  0.179374)

両方のシンボルテストは、速度に関して基本的に同じです。 1,000,000回の反復の後、差は0.004733秒しかないため、どちらを使用するかは間違えないと思います。

44
the Tin Man

シンボルは、Rubyで文字列と名前を表す方法です。

シンボルと文字列の主な違いは、同じ名前のシンボルが初期化され、Rubyのセッション中に一度だけメモリに存在することです。

同じWordを使用して異なるものを表す必要がある場合に便利です。

30
nunopolonia

symbolも理解するのに役立つかもしれない有名な本 RailsでのアジャイルWeb開発 からの引用があります:

Railsは、シンボルを使用して物事を識別します。特に、メソッドのパラメーターに名前を付け、ハッシュで物事を調べるときにキーとして使用します。

redirect_to :action => "edit", :id => params[:id]

シンボルは、魔法のように定数にされた文字列リテラルと考えることができます。または、コロンは「名前が付けられたもの」を意味すると考えることができます。したがって、:idは「名前が付けられたもの」です。

16
shyan1

Rubyでは、各オブジェクトに一意のオブジェクト識別子があり、puts "hello".object_idをirbに書き込んで2回異なるリターンを押すと、2つの異なる戻り値を取得しますが、:hello.object_idを2回書き込むと、同じ値を返します。それが違いを説明しているはずです。

4
Devin Huang

:foo => barを使用する場合、fooはシンボルになります。シンボルの利点は、シンボルが一意であることです。ハッシュ内のアイテムを呼び出すと、hash[:foo]を実行します。

シンボルは文字列よりもメモリを必要としないため、プログラムを少し速くしたい場合にも役立ちます。

2
Charles

これらのすべての答えは、1つの余分な食欲をそそる詳細を省略します。シンボルfooを文字列化すると、文字列 "foo"が得られます。したがって

irb(main):025:0>
irb(main):026:0> :foo
=> :foo
irb(main):027:0> "#{:foo}"
=> "foo"
irb(main):028:0>
irb(main):029:0> 'foo' <=> :foo
=> nil
irb(main):030:0> 'foo' <=> :foo.to_s
=> 0
irb(main):031:0>

したがって、.. Perlプログラマーにとっては、「裸の言葉」に対するRubyの答えです。

0
Frank Carnovale

それはシンボルです。基本的に、ハッシュの2つの要素にはキーblabloopがあり、文字列"bla""bloop"を使用したかのように言っています。ただし、文字列よりもメモリを消費せず、入力しやすいです。

0
kindall