Ответ 1
TL; DR
Простое эмпирическое правило - использовать символы каждый раз, когда вам нужны внутренние идентификаторы. Для Ruby < 2.2 используются только символы, если они не генерируются динамически, чтобы избежать утечек памяти.
Полный ответ
Единственная причина не использовать их для идентификаторов, которые генерируются динамически из-за проблем с памятью.
Этот вопрос очень распространен, потому что многие языки программирования не имеют символов, только строк, и поэтому строки также используются в качестве идентификаторов в вашем коде. Вы должны беспокоиться о том, какие символы должны быть, а не только когда вы должны использовать символы. Символы должны быть идентификаторами. Если вы будете следовать этой философии, скорее всего, вы все сделаете правильно.
Существует несколько различий между реализацией символов и строк. Самое важное в символах - это неизменный. Это означает, что они никогда не изменят свою ценность. Из-за этого символы создаются быстрее, чем строки, и некоторые операции, такие как сравнение двух символов, также быстрее.
Тот факт, что символ неизменен, позволяет Ruby использовать один и тот же объект каждый раз, когда вы ссылаетесь на символ, сохраняя память. Поэтому каждый раз, когда интерпретатор читает :my_key
, он может взять его из памяти, а не создавать его снова. Это меньше, чем инициализация новой строки каждый раз.
Вы можете получить список всех символов, которые уже были созданы с помощью команды Symbol.all_symbols
:
symbols_count = Symbol.all_symbols.count # all_symbols is an array with all
# instantiated symbols.
a = :one
puts a.object_id
# prints 167778
a = :two
puts a.object_id
# prints 167858
a = :one
puts a.object_id
# prints 167778 again - the same object_id from the first time!
puts Symbol.all_symbols.count - symbols_count
# prints 2, the two objects we created.
Для версий Ruby до 2.2 после создания символа эта память никогда не будет свободной снова. Единственный способ освободить память - это перезапустить приложение. Таким образом, символы также являются основной причиной утечки памяти при неправильном использовании. Самый простой способ генерации утечки памяти - использовать метод to_sym
для пользовательских входных данных, так как эти данные будут всегда меняться, новая часть памяти будет использоваться навсегда в экземпляре программного обеспечения. Ruby 2.2 представил сборщик мусора символов, который освобождает символы, сгенерированные динамически, поэтому утечки памяти, генерируемые динамическим путем создания символов, больше не беспокоят.
Отвечая на ваш вопрос:
Правда ли, что я должен использовать символ вместо строки, если в моем приложении есть по крайней мере две одинаковые строки или script?
Если вы ищете идентификатор, который будет использоваться внутри вашего кода, вы должны использовать символы. Если вы печатаете вывод, вы должны идти со строками, даже если он появляется более одного раза, даже выделяя два разных объекта в памяти.
Здесь рассуждения:
- Печать символов будет медленнее, чем печать строк, потому что они передаются в строки.
- Наличие большого количества разных символов увеличит общее использование памяти вашего приложения, поскольку они никогда не будут освобождены. И вы никогда не используете все строки из своего кода одновременно.
Использовать регистр @AlanDert
@AlanDert: если я использую много раз что-то вроде% input {type:: checkbox} в haml-коде, что я должен использовать как флажок?
Me: Да.
@AlanDert: Но чтобы распечатать символ на странице html, он должен быть преобразован в строку, не так ли? какой смысл использовать его?
Каков тип ввода? Идентификатор типа ввода, который вы хотите использовать, или того, что вы хотите показать пользователю?
Верно, что в какой-то момент он станет HTML-кодом, но на данный момент вы пишете эту строку своего кода, это значит быть идентификатором - он определяет, какое поле ввода вам нужно. Таким образом, он используется снова и снова в вашем коде и всегда имеет ту же "строку" символов, что и идентификатор, и не будет генерировать утечку памяти.
Тем не менее, почему мы не оцениваем данные, чтобы увидеть, быстрее ли строки?
Это простой тест, который я создал для этого:
require 'benchmark'
require 'haml'
str = Benchmark.measure do
10_000.times do
Haml::Engine.new('%input{type: "checkbox"}').render
end
end.total
sym = Benchmark.measure do
10_000.times do
Haml::Engine.new('%input{type: :checkbox}').render
end
end.total
puts "String: " + str.to_s
puts "Symbol: " + sym.to_s
Три выхода:
# first time
String: 5.14
Symbol: 5.07
#second
String: 5.29
Symbol: 5.050000000000001
#third
String: 4.7700000000000005
Symbol: 4.68
Таким образом, использование smbols на самом деле немного быстрее, чем использование строк. Почему это? Это зависит от способа реализации HAML. Мне нужно немного взломать код HAML, но если вы будете использовать символы в концепции идентификатора, ваше приложение будет быстрее и надежнее. Когда вопросы забавляются, сравнивайте и получайте ответы.