Ruby'deki iki nokta üst üste operatörü nedir?


Yanıtlar:


249

: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.


2
sadece değişmez dize neden dize stajyer desteklemiyor merak ediyorum?
onmyway133

5
@ onmyway133 Çünkü Ruby dizeleri değişebilir. Staj sadece değişmeyen değerler için geçerlidir.
Chris Jester-Young

3
a) Neden "foo".equal? "foo"yanlış? b) Herhangi bir yerde bir sembole başvurabilir misiniz, aslında küresel değişkenler gibi?
Arc676

2
@ Arc676 1. 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.
Chris Jester-Young

2
@ Arc676 "foo" == "foo"# => doğru
Filip Bartuzi

44

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.


Son derece yardımcı! Sistemimde, hem dize hem de sembol karşılaştırmalarına ==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.
melvynkim

33

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


19

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.


5

Ruby'de her nesnenin benzersiz bir nesne tanımlayıcısı vardır, eğer puts "hello".object_idirb'nize yazıp 2 farklı kez geri dönüş yaparsanız, 2 farklı geri dönüş değeri elde edersiniz, ancak :hello.object_id2 kez yazarsanız, yalnızca aynı dönen değeri alırsınız. Bu farkı açıklamalıydı.


Temel olarak iki nokta üst üste operatörü bir sembol
Cesar Jr Rodriguez

2

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.


0

Bu bir sembol. Temel olarak, karma iki element anahtarlarına sahip söylüyor blave bloopsen dizeleri kullanmıştı çok sanki "bla"ve "bloop". Ancak, dizelerden daha az bellek kaplarlar ve yazmaları daha kolaydır.


0

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ı.


-1

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 :symbolgelmesi 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.


1
Sembollerin değişmez olması, uygulamanız boyunca her zaman aynı örnek olmasını sağlar ve bu nedenle aynı nesne olmaları garanti edilir. Bu başvuruları kontrol edin: troubleshooters.com/codecorn/ruby/symbols.htm robertsosinski.com/2009/01/11/... You daha google eğer yükleri bulabilirsiniz.
Dhruva Sagar

Java'ya benzetmenizden bahsediyorum. Java Dizeleri sembollere benzemez. Java dize değişmezleri tüm dizeler değil, dizelerdir.
smartnut007

Belki de ifadem yeterince açık değildi. Birbirlerine sadece değişmez oldukları gerçeğine göre benzerler.
Dhruva Sagar

@DhruvaSagar: Objective C'leri kullandıysanız benzetme daha iyi olurdu 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.
Rafael Bugajewski
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.