Когда я говорю { :bla => 1, :bloop => 2 }
, что именно делает :
? Я где-то читал о том, как это похоже на строку, но как-то символ.
Я не очень ясен в концепции, кто-то может просветить меня?
Когда я говорю { :bla => 1, :bloop => 2 }
, что именно делает :
? Я где-то читал о том, как это похоже на строку, но как-то символ.
Я не очень ясен в концепции, кто-то может просветить меня?
Ответы:
:foo
это символ с именем "foo". Символы имеют отличительную особенность в том, что любые два символа с одинаковыми именами будут идентичны:
"foo".equal? "foo" # false
:foo.equal? :foo # true
Это делает сравнение двух символов действительно быстрым (поскольку проводится сравнение только по указателю, а не по сравнению со всеми символами, как в строке), плюс у вас не будет плавать миллионы копий одного и того же символа.
Кроме того, в отличие от строк, символы являются неизменными.
"foo".equal? "foo"
ложно? б) Можете ли вы ссылаться на символ в любом месте, по существу делая их как глобальные переменные?
equal?
в Ruby происходит сравнение тождеств. Каждый строковый литерал, например "foo"
, создает новый экземпляр строки. Это работает так, потому что строки в Ruby являются изменяемыми. 2. Символы являются глобальными, но больше похожи на глобальные константы, чем на глобальные переменные, поскольку символы не имеют состояния. Таким образом, использование символов не является антипаттерном в смысле глобальных переменных.
"foo" == "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 секунды, так что я бы сказал, что между ними стоит промывка.
==
результат получился быстрее, чем .equal?
для сравнения строк и символов. Сравнение символов в 3 раза быстрее, чем сравнение строк.
Символы - это способ представления строк и имен в ruby.
Основное различие между символами и строками состоит в том, что символы с одинаковым именем инициализируются и существуют в памяти только один раз во время сеанса ruby.
Они полезны, когда вам нужно использовать одно и то же слово, чтобы представлять разные вещи
Вот несколько цитат из известной книги Agile Web Development с Rails , которая может быть полезна и для понимания символа :
Rails использует символы для идентификации вещей. В частности, он использует их в качестве ключей при именовании параметров метода и поиске вещей в хешах.
redirect_to :action => "edit", :id => params[:id]
Вы можете думать о символах как о строковых литералах, которые волшебным образом превращаются в константы. В качестве альтернативы, вы можете считать двоеточие означающим «вещь с именем», поэтому: id - это «вещь с именем id».
В ruby каждый объект имеет уникальный идентификатор объекта, если вы напишите puts "hello".object_id
в своем irb и нажмете return два раза, вы получите 2 разных возвращаемых значения, но если вы напишите :hello.object_id
2 раза, вы получите только одно возвращаемое значение. Это должно было объяснить разницу.
Если вы используете :foo => bar
, foo будет символом. Преимущество символов в том, что они уникальны. Когда вы вызываете элемент в хэше, вы делаете hash[:foo]
.
Символы требуют меньше памяти, чем строки, что также делает их полезными, если вы хотите сделать свою программу немного быстрее.
Во всех этих ответах пропущена одна дополнительная заманчивая деталь ... если вы зафиксируете символ: 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 ... это ответ Руби на "голое слово".
Если вы знакомы с Java, вы можете знать, что строки в Java являются неизменяемыми. Символы похожи в этом смысле в Ruby. Они являются неизменными, т. Е. Любое количество вхождений конкретного символа :symbol
будет отображаться только на один адрес памяти. И, следовательно, рекомендуется использовать символы везде, где это возможно, поскольку это оптимизирует использование памяти.
NSString
. Там "foo"
всегда будет равна "foo"
, потому что внутренне строки , которые являются такими же , как раз указывают на. Ответ все еще будет сбивать с толку, хотя.