Что такое оператор двоеточия в Ruby?

когда я говорю { :bla => 1, :bloop => 2 }, что именно : сделать? Я где-то читал о том, как это похоже на строку, но как-то символ.

Я не супер-ясно на концепции, может кто-то просветить меня?

9 ответов


:foo - символ с именем "foo". Символы имеют отличительную особенность, что любые два символа с одинаковыми именами будут идентичны:

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

это делает сравнение двух символов очень быстрым (так как используется только сравнение указателей, а не сравнение всех символов, как в строке), плюс у вас не будет миллионов копий одного и того же символа, плавающего вокруг.

кроме того, в отличие от строк, символы неизменяемы.


просто чтобы продемонстрировать некоторые из вещей, упомянутых в ответах:

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 второе отличие, поэтому я бы сказал, что это стирание между ними.


символы-это способ представления строк и имен в ruby.

основное различие между символами и строками заключается в том, что символы с тем же именем инициализируются и существуют в памяти только один раз во время сеанса ruby.

Они полезны, когда вам нужно использовать одно и то же слово для представления разных вещей


есть несколько цитат из знаменитой книги гибкая Веб-разработка с Rails, что может быть полезно для понимания символ а также :

Rails использует символы для идентификации вещей. В частности, он использует их в качестве ключей при именовании параметров метода и поиске вещей в хэшах.

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

вы можете думать о символах как о строковых литералах, которые волшебным образом превращаются в константы. Кроме того, вы можете рассмотрим двоеточие как "вещь с именем", поэтому :id-это"вещь с именем id".


в Ruby каждый объект имеет уникальный идентификатор объекта, если вы пишите puts "hello".object_id в вашем irb и нажмите return в течение 2 разных раз, вы получите 2 разных возвращаемого значения, но если вы напишете :hello.object_id 2 раза вы получите только одно возвращаемое значение. Это должно было объяснить разницу.


Если вы используете :foo => bar, foo будет символом. Преимущество символов в том, что они уникальны. Когда вы вызываете элемент в хэше, вы делаете hash[:foo].

символы требуют меньше памяти, чем строки, что также делает их полезными, если вы хотите сделать вашу программу чуть быстрее.


это символ. В принципе, вы говорите, что два элемента хэша имеют ключи bla и bloop, как если бы вы использовали строки "bla" и "bloop". Однако они занимают меньше памяти, чем строки, и их легче вводить.


все эти ответы опускают одну дополнительную дразнящую деталь.. если вы строчите символ: 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-программистов.. это ответ Руби на "голое слово".


Если вы знакомы с Java, вы можете знать, что строки в Java неизменяемы. Символы схожи в этом смысле в Ruby. Они неизменны, то есть любое количество вхождений определенного символа :symbol будет отображаться только на один адрес памяти. И, следовательно, рекомендуется использовать символы везде, где это возможно, поскольку это оптимизирует использование памяти.