Komut dizimde aynı dizenin en az iki örneği varsa bunun yerine bir sembol kullanmalı mıyım?
Komut dizimde aynı dizenin en az iki örneği varsa bunun yerine bir sembol kullanmalı mıyım?
Yanıtlar:
Basit bir temel kural, dahili tanımlayıcılara her ihtiyaç duyduğunuzda sembolleri kullanmaktır. Ruby <2.2 için, bellek sızıntılarını önlemek için, sembolleri yalnızca dinamik olarak oluşturulmadıklarında kullanın.
Bunları dinamik olarak oluşturulan tanımlayıcılar için kullanmamanın tek nedeni bellek endişeleridir.
Bu soru çok yaygındır çünkü birçok programlama dilinde semboller yoktur, yalnızca dizeler vardır ve bu nedenle dizeler kodunuzda tanımlayıcılar olarak da kullanılır. Sen semboller ne hakkında endişe verici olmalıdır olması gerekiyordu sadece, sen sembolleri kullanılmalıdır zaman . Sembollerin tanımlayıcı olması amaçlanmıştır. Bu felsefeyi takip ederseniz, işleri doğru yapma şansınız vardır.
Sembollerin ve dizelerin uygulanması arasında birkaç fark vardır. Sembollerle ilgili en önemli şey, değişmez olmalarıdır . Bu, değerlerini asla değiştirmeyecekleri anlamına gelir. Bu nedenle, semboller dizelerden daha hızlı başlatılır ve iki sembolü karşılaştırmak gibi bazı işlemler de daha hızlıdır.
Bir sembolün değişmez olması gerçeği, Ruby'nin sembole her başvurduğunuzda aynı nesneyi kullanmasına ve hafızadan tasarruf etmesine izin verir. Dolayısıyla, yorumlayıcı her okuduğunda :my_key, yeniden örneklemek yerine onu bellekten alabilir. Bu, her seferinde yeni bir dizge başlatmaktan daha ucuzdur.
Şu komutla halihazırda somutlaştırılmış tüm sembollerin bir listesini alabilirsiniz 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.
2.2'den önceki Ruby sürümleri için, bir sembol somutlaştırıldığında, bu bellek bir daha asla serbest olmayacaktır . Belleği boşaltmanın tek yolu uygulamayı yeniden başlatmaktır. Bu nedenle semboller, yanlış kullanıldığında bellek sızıntılarının önemli bir nedenidir. Bir bellek sızıntısı oluşturmanın en basit yolu, yöntemi to_symkullanıcı girdi verilerinde kullanmaktır, çünkü bu veriler her zaman değişeceğinden, belleğin yeni bir kısmı yazılım örneğinde sonsuza kadar kullanılacaktır. Ruby 2.2 , dinamik olarak oluşturulan sembolleri serbest bırakan sembol çöp toplayıcıyı tanıttı , böylece dinamik olarak semboller oluşturarak üretilen bellek sızıntıları artık bir sorun değil.
Sorunuzu cevaplamak:
Uygulamamda veya komut dosyamda aynı dizelerden en az iki tane varsa, dize yerine bir sembol kullanmam gerektiği doğru mu?
Aradığınız şey kodunuzda dahili olarak kullanılacak bir tanımlayıcıysa, semboller kullanıyor olmalısınız. Çıktı yazdırıyorsanız, birden fazla görünse bile, bellekte iki farklı nesne tahsis etseniz bile dizelerle gitmelisiniz.
Nedeni şu:
@AlanDert: Haml kodunda birçok kez% input {type:: checkbox} gibi bir şey kullanırsam, onay kutusu olarak ne kullanmalıyım?
Ben evet.
@AlanDert: Ama html sayfasına bir sembol yazdırmak için dizeye dönüştürülmeli, değil mi? o zaman kullanmanın anlamı ne?
Bir girdinin türü nedir? Kullanmak istediğiniz giriş türünün bir tanımlayıcısı mı yoksa kullanıcıya göstermek istediğiniz bir şey mi?
Bir noktada HTML kodu olacağı doğrudur, ancak şu anda kodunuzun o satırını yazarken, bu bir tanımlayıcı anlamına gelir - ne tür bir giriş alanına ihtiyacınız olduğunu tanımlar. Bu nedenle, kodunuzda tekrar tekrar kullanılır ve her zaman tanımlayıcı olarak aynı "karakter dizisine" sahiptir ve bir bellek sızıntısı oluşturmaz.
Bununla birlikte, dizelerin daha hızlı olup olmadığını görmek için neden verileri değerlendirmiyoruz?
Bu, bunun için oluşturduğum basit bir ölçüt:
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
Üç çıkış:
# first time
String: 5.14
Symbol: 5.07
#second
String: 5.29
Symbol: 5.050000000000001
#third
String: 4.7700000000000005
Symbol: 4.68
Yani smbols kullanmak aslında dizeleri kullanmaktan biraz daha hızlı. Neden? HAML'nin uygulanma şekline bağlıdır. Görmek için HAML kodunu biraz kırmam gerekecek, ancak bir tanımlayıcı konseptindeki sembolleri kullanmaya devam ederseniz, uygulamanız daha hızlı ve güvenilir olacaktır. Sorular ortaya çıktığında, onu kıyaslayın ve cevaplarınızı alın.
Basitçe ifade etmek gerekirse, bir sembol, karakterlerden oluşan ancak değişmez bir isimdir. Aksine, dizge, içeriklerinin değişmesine izin verilen karakterler için sıralı bir kaptır.
Codecademy'de bulduğum güzel dizeler ve semboller karşılaştırması:
require 'benchmark'
string_AZ = Hash[("a".."z").to_a.zip((1..26).to_a)]
symbol_AZ = Hash[(:a..:z).to_a.zip((1..26).to_a)]
string_time = Benchmark.realtime do
1000_000.times { string_AZ["r"] }
end
symbol_time = Benchmark.realtime do
1000_000.times { symbol_AZ[:r] }
end
puts "String time: #{string_time} seconds."
puts "Symbol time: #{symbol_time} seconds."
Çıktı:
String time: 0.21983 seconds.
Symbol time: 0.087873 seconds.
hash anahtarı tanımlayıcıları olarak sembolleri kullanın
{key: "value"}
semboller yöntemi farklı bir sırayla çağırmanıza izin verir
def write (dosya :, veri :, mod: "ascii")
# kısalık için kaldırıldı
son
yazma (veri: 123, dosya: "test.txt")
dize olarak tutmak ve hafızadan tasarruf etmek için dondurun
label = 'My Label'.freeze
/(sonrastrings) kaldırmanız gerekir . İşte: www.reactive.io/tips/2009/01/11/the-difference-between-ruby- symbols-and-strings