Söylediğimde { :bla => 1, :bloop => 2 }
tam olarak ne yapar :
? Bir dizeye nasıl benzediğini bir yerde okudum, ama bir şekilde bir sembol.
Konsept konusunda çok net değilim, biri beni aydınlatabilir mi?
Söylediğimde { :bla => 1, :bloop => 2 }
tam olarak ne yapar :
? Bir dizeye nasıl benzediğini bir yerde okudum, ama bir şekilde bir sembol.
Konsept konusunda çok net değilim, biri beni aydınlatabilir mi?
Yanıtlar:
:foo
"foo" adlı bir semboldür. Semboller, aynı adlı iki sembolün aynı olacağı farklı bir özelliğe sahiptir:
"foo".equal? "foo" # false
:foo.equal? :foo # true
Bu, iki simgeyi karşılaştırmayı gerçekten hızlı hale getirir (bir dizede yaptığınız gibi tüm karakterleri karşılaştırmak yerine yalnızca bir işaretçi karşılaştırması söz konusudur), ayrıca aynı sembolün milyonlarca kopyası kalamazsınız.
Ayrıca, dizelerden farklı olarak, semboller değişmezdir.
"foo".equal? "foo"
yanlış? b) Herhangi bir yerde bir sembole başvurabilir misiniz, aslında küresel değişkenler gibi?
equal?
Ruby'de kimlik karşılaştırması yapar. Her dize hazır bilgisi, "foo"
yeni bir dize örneği oluşturur. Bu şekilde çalışır, çünkü Ruby'deki dizeler değiştirilebilir. 2. Semboller geneldir, ancak sembollerin durumu olmadığı için küresel değişkenlerden daha çok küresel sabitler gibidir. Dolayısıyla sembollerin kullanılması, küresel değişkenlerin olduğu gibi bir antipattern değildir.
"foo" == "foo"
# => doğru
Sadece cevaplarda bahsedilen bazı şeyleri göstermek için:
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
Çalıştırma çıktıları:
"foo".equal? "foo" -> false
"foo" == "foo" -> true
:foo.equal? :foo -> true
:foo == :foo -> true
Dolayısıyla, equal?
eşit içerik olsalar bile farklı nesneler oldukları için bir dizeyi dize ile karşılaştırmak başarısız olur. ==
içeriği karşılaştırır ve sembollerle eşdeğer kontroller çok daha hızlıdır.
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)
Her iki sembol testi de temel olarak hız ile aynıdır. 1.000.000 yinelemeden sonra sadece 0.004733 saniye farkı var, bu yüzden aralarında bir yıkama olduğunu söyleyebilirim.
==
göre daha hızlı sonuçlandı .equal?
. Sembol karşılaştırması, dize karşılaştırmalarından 3 kat daha hızlı sonuç verdi.
Semboller, yakuttaki dizeleri ve isimleri temsil etmenin bir yoludur.
Semboller ve dizeler arasındaki temel fark, aynı adı taşıyan sembollerin bir yakut oturumu sırasında yalnızca bir kez başlatılır ve bellekte var olmasıdır.
Farklı şeyleri temsil etmek için aynı kelimeyi kullanmanız gerektiğinde yararlıdırlar
Sembolü anlamanıza yardımcı olabilecek ünlü Rails with Agils Web Development adlı ünlü kitabından bazı alıntılar var :
Raylar şeyleri tanımlamak için semboller kullanır. Özellikle, yöntem parametrelerini adlandırırken ve karma değerlere bakarken bunları anahtar olarak kullanır.
redirect_to :action => "edit", :id => params[:id]
Sembolleri, sihirli bir şekilde sabitler haline getirilmiş dize değişmezleri olarak düşünebilirsiniz. Alternatif olarak, iki nokta üst üste işaretini "adlı şey" anlamına da düşünebilirsiniz, bu nedenle: id "id" adlı şeydir.
Ruby'de her nesnenin benzersiz bir nesne tanımlayıcısı vardır, eğer puts "hello".object_id
irb'nize yazıp 2 farklı kez geri dönüş yaparsanız, 2 farklı geri dönüş değeri elde edersiniz, ancak :hello.object_id
2 kez yazarsanız, yalnızca aynı dönen değeri alırsınız. Bu farkı açıklamalıydı.
Eğer kullanırsanız :foo => bar
, foo bir sembol olacaktır. Sembollerin yararı, benzersiz olmalarıdır. Karma bir öğeyi çağırdığınızda, yaparsınız hash[:foo]
.
Semboller dizelerden daha az bellek gerektirir, bu da programınızı biraz daha hızlı yapmak istiyorsanız bunları kullanışlı hale getirir.
Tüm bu cevaplar fazladan bir ayrıntıyı atlar .. Eğer sembolü dize ederseniz: foo, anladınız .. tahmin edin .. "foo" dizesi. bundan dolayı
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>
Bu yüzden .. Perl programcıları için .. Ruby'nin 'çıplak kelimeye' cevabı.
Java'ya aşina iseniz, Java'daki Dizelerin değişmez olduğunu biliyor olabilirsiniz. Semboller bu anlamda Ruby'de benzerdir. Değişmezler, yani belirli bir sembolün herhangi bir sayıda meydana :symbol
gelmesi yalnızca tek bir bellek adresine eşlenir. Bu nedenle, bellek kullanımını optimize ettiği için mümkün olan yerlerde sembollerin kullanılması önerilir.
NSString
. Her "foo"
zaman eşit olacaktır "foo"
, çünkü aynı olan dahili dizeler sadece işaret edilir. Yine de cevap hala kafa karıştırıcı olurdu.