Коли я кажу { :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"
# => вірно
Тільки щоб продемонструвати деякі речі, згадані у відповідях:
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+ рази швидше порівняння з рядками.
Символи - це спосіб представити рядки та імена в рубіні.
Основна відмінність символів і рядків полягає в тому, що символи з однойменною ініціалізацією ініціалізуються і існують у пам'яті лише один раз під час сеансу рубіну.
Вони корисні, коли вам потрібно використовувати одне й те саме слово для представлення різних речей
Ось цитати з відомої книги Agile Web Development with Rails , які можуть бути корисними і для розуміння символу :
Рейки використовують символи для ідентифікації речей. Зокрема, він використовує їх як ключі під час іменування параметрів методу та пошуку речей у хешах.
redirect_to :action => "edit", :id => params[:id]
Ви можете думати про символи як рядкові буквали, які магічно перетворюються на константи. Крім того, ви можете вважати, що двокрапка означає "річ, яку називають", так: id - це "річ з ім'ям id".
У рубіні кожного об'єкта є унікальний ідентифікатор об'єкта, якщо ви puts "hello".object_id
запишете у ваш irb і натисніть на віддачу протягом 2 різних разів, ви отримаєте 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 незмінні. Символи подібні в цьому сенсі у Рубі. Вони незмінні, тобто будь-яка кількість випадків певного символу :symbol
відображатиметься лише до однієї адреси пам'яті. І, отже, рекомендується використовувати символи, де це можливо, оскільки це оптимізує використання пам'яті.
NSString
. Там "foo"
завжди буде дорівнює "foo"
, тому що внутрішньо рядки , які є такими ж , як раз вказують на. Однак відповідь все-таки буде заплутаною.