Apa operator usus besar di Ruby?

234

Ketika saya mengatakan { :bla => 1, :bloop => 2 }, apa sebenarnya yang :harus dilakukan? Saya membaca di suatu tempat tentang bagaimana itu mirip dengan string, tetapi entah bagaimana simbol.

Saya tidak terlalu jernih pada konsepnya, bisakah seseorang mencerahkan saya?

LuxuryMode
sumber
1
kemungkinan rangkap dari Memahami Simbol Di Ruby
Mladen Jablanović
7
Coba lihat ini: The Ruby_Newbie Guide to Symbols
Hengjie
Video ini memberi tahu Anda segala yang perlu Anda ketahui tentang simbol.
totymedli

Jawaban:

249

:fooadalah simbol bernama "foo". Simbol memiliki fitur berbeda yang mana dua simbol dengan nama yang sama akan identik:

"foo".equal? "foo"  # false
:foo.equal? :foo    # true

Ini membuat membandingkan dua simbol sangat cepat (karena hanya perbandingan pointer yang terlibat, dibandingkan dengan membandingkan semua karakter seperti yang Anda lakukan dalam string), ditambah Anda tidak akan memiliki miliaran salinan simbol yang sama melayang-layang.

Juga, tidak seperti string, simbol tidak dapat diubah.

Chris Jester-Young
sumber
2
hanya ingin tahu mengapa string literal tidak mendukung string interning?
onmyway133
5
@ onmyway133 Karena string Ruby bisa berubah. Interning hanya berlaku untuk nilai yang tidak berubah.
Chris Jester-Young
3
a) Mengapa "foo".equal? "foo"salah? b) Dapatkah Anda merujuk pada simbol di mana saja, pada dasarnya menjadikannya seperti variabel global?
Arc676
2
@ Arc676 1. equal?di Ruby melakukan perbandingan identitas. Setiap string literal, seperti "foo", membuat instance string baru. Ini berfungsi seperti itu karena string di Ruby bisa berubah. 2. Simbol bersifat global, tetapi lebih mirip konstanta global daripada variabel global, karena simbol tidak memiliki status. Jadi, menggunakan simbol bukanlah antipengganti dalam cara variabel global.
Chris Jester-Young
2
@ Arc676 "foo" == "foo"# => true
Filip Bartuzi
44

Hanya untuk menunjukkan beberapa hal yang disebutkan dalam jawaban:

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

Menjalankannya menghasilkan:

"foo".equal? "foo" -> false
"foo" == "foo"     -> true
:foo.equal? :foo   -> true
:foo == :foo       -> true

Jadi, membandingkan string ke string menggunakan equal?gagal karena mereka objek yang berbeda, bahkan jika mereka konten yang sama. ==membandingkan konten, dan pemeriksaan setara dengan simbol jauh lebih cepat.

                 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)

Kedua tes simbol pada dasarnya sama sejauh kecepatan. Setelah 1.000.000 iterasi hanya ada perbedaan 0,004733 detik, jadi saya akan mengatakan itu adalah mencuci yang digunakan.

Manusia Timah
sumber
Sangat membantu! Di sistem saya, hasil ==lebih cepat daripada .equal?perbandingan string dan simbol. Perbandingan simbol menghasilkan 3+ kali lebih cepat dari perbandingan string.
melvynkim
33

Simbol adalah cara untuk mewakili string dan nama dalam ruby.

Perbedaan utama antara simbol dan string adalah bahwa simbol dengan nama yang sama diinisialisasi dan ada di memori hanya sekali selama sesi ruby.

Mereka berguna ketika Anda perlu menggunakan kata yang sama untuk mewakili hal-hal yang berbeda

nunopolonia
sumber
19

Ada beberapa kutipan dari buku terkenal Agile Web Development with Rails , yang mungkin membantu untuk memahami simbol juga:

Rails menggunakan simbol untuk mengidentifikasi hal-hal. Secara khusus, ini menggunakannya sebagai kunci ketika menamai parameter metode dan mencari hal-hal dalam hash.

redirect_to :action => "edit", :id => params[:id]

Anda dapat menganggap simbol sebagai string literal yang secara ajaib dibuat menjadi konstanta. Atau, Anda dapat menganggap titik dua berarti "nama yang dinamai", jadi: id adalah "nama yang dinamai id".

shyan1
sumber
5

Dalam ruby, setiap objek memiliki pengenal objek yang unik, jika Anda menulis puts "hello".object_iddi irb dan menekan return untuk 2 kali yang berbeda, Anda akan mendapatkan 2 nilai pengembalian yang berbeda, tetapi jika Anda menulis :hello.object_id2 kali Anda hanya akan mendapatkan nilai pengembalian yang sama. Itu seharusnya menjelaskan perbedaannya.

Devin Huang
sumber
Pada dasarnya operator titik dua adalah untuk menetapkan simbol
Cesar Jr Rodriguez
2

Jika Anda menggunakan :foo => bar, foo akan menjadi simbol. Manfaat simbol adalah unik. Ketika Anda memanggil item dalam hash, Anda lakukan hash[:foo].

Simbol membutuhkan lebih sedikit memori daripada string, yang juga membuatnya berguna jika Anda ingin membuat program Anda sedikit lebih cepat.

Charles
sumber
0

Itu simbol. Pada dasarnya, Anda mengatakan bahwa dua elemen hash memiliki kunci bladan bloop, seolah-olah Anda telah menggunakan string "bla"dan "bloop". Namun, mereka mengambil lebih sedikit memori daripada string dan lebih mudah untuk mengetik.

baik hati
sumber
0

Semua jawaban ini menghilangkan satu detail ekstra yang menggiurkan .. jika Anda merangkai simbol: foo, Anda dapatkan .. tebak apa .. string "foo". Karenanya

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>

Karenanya .. untuk programmer Perl .. itu jawaban Ruby untuk 'kata kosong'.

Frank Carnovale
sumber
-1

Jika Anda terbiasa dengan Java, Anda mungkin menyadari bahwa String di Java tidak dapat diubah. Simbol serupa dalam arti itu di Ruby. Mereka tidak berubah, yaitu, sejumlah kejadian simbol tertentu :symbolakan memetakan hanya ke satu alamat memori. Dan, karenanya, disarankan untuk menggunakan simbol sedapat mungkin karena mengoptimalkan penggunaan memori.

Dhruva Sagar
sumber
1
Fakta bahwa simbol tidak berubah memastikan bahwa mereka selalu menjadi contoh yang sama di seluruh aplikasi Anda dan karenanya mereka dijamin menjadi objek yang sama. Periksa referensi ini: troubleshooters.com/codecorn/ruby/symbols.htm robertsosinski.com/2009/01/11/... Anda akan menemukan banyak lagi jika Anda google.
Dhruva Sagar
Saya berbicara tentang analogi Anda dengan Jawa. String Java tidak analog dengan simbol. String Jawa literal tetapi tidak semua string.
smartnut007
Mungkin pernyataan saya tidak cukup jelas. Mereka analog satu sama lain hanya sehubungan dengan fakta bahwa mereka tidak berubah.
Dhruva Sagar
@ DhruvaSagar: Analogi akan lebih baik jika Anda menggunakan Objective C's NSString. Akan "foo"selalu ada yang sama dengan "foo", karena string internal yang sama hanya ditunjukkan. Namun, jawabannya tetap membingungkan.
Rafael Bugajewski