ตัวดำเนินการโคลอนใน Ruby คืออะไร


234

เมื่อฉันพูด{ :bla => 1, :bloop => 2 }สิ่งที่ว่าจะ:ทำอย่างไร ฉันอ่านบางที่เกี่ยวกับความคล้ายคลึงกับสตริง แต่อย่างใดสัญลักษณ์

ฉันไม่ชัดเจนในแนวคิดนี้ใครจะช่วยสอนฉันได้บ้าง


1
ความเป็นไปได้ที่ซ้ำกันของสัญลักษณ์การทำความเข้าใจในทับทิม
Mladen Jablanović


วิดีโอนี้บอกทุกสิ่งที่คุณจำเป็นต้องรู้เกี่ยวกับสัญลักษณ์
totymedli

คำตอบ:


249

:fooเป็นสัญลักษณ์ที่ชื่อว่า "foo" สัญลักษณ์มีคุณสมบัติที่แตกต่างกันซึ่งสัญลักษณ์สองชื่อที่เหมือนกันจะเหมือนกัน:

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

สิ่งนี้ทำให้การเปรียบเทียบสัญลักษณ์สองตัวนั้นเร็วมาก (เนื่องจากมีการเปรียบเทียบตัวชี้เท่านั้นซึ่งต่างจากการเปรียบเทียบอักขระทั้งหมดที่คุณต้องการในสตริง) และคุณจะไม่มีสำเนาเดียวกันที่มีสัญลักษณ์พันล้านตัวที่ลอยอยู่

นอกจากนี้ยังแตกต่างจากสตริงสัญลักษณ์ที่ไม่เปลี่ยนรูป


2
แค่สงสัยว่าทำไมสตริงตัวอักษรไม่สนับสนุนการฝึกงานสตริง?
onmyway133

5
@ onmyway133 เนื่องจากสตริงของ Ruby สามารถเปลี่ยนแปลงได้ การใช้งานเฉพาะกับค่าที่ไม่เปลี่ยนรูปเท่านั้น
Chris Jester-Young

3
ก) ทำไมจึงเป็น"foo".equal? "foo"เท็จ b) คุณสามารถอ้างถึงสัญลักษณ์ได้ทุกที่ทำให้พวกเขาเป็นเหมือนตัวแปรทั่วโลก?
Arc676

2
@ Arc676 1. equal?ใน Ruby ทำการเปรียบเทียบตัวตน สตริงแต่ละตัวอักษรเช่น"foo"สร้างสตริงอินสแตนซ์ใหม่ มันทำงานได้อย่างนั้นเพราะสตริงใน Ruby นั้นไม่แน่นอน 2. สัญลักษณ์เป็นโลก แต่คล้ายกับค่าคงที่ทั่วโลกมากกว่าตัวแปรทั่วโลกเนื่องจากสัญลักษณ์ไม่มีสถานะ ดังนั้นการใช้สัญลักษณ์ไม่ใช่ปฏิสสารในลักษณะที่ตัวแปรทั่วโลกเป็น
Chris Jester-Young

2
@ Arc676 "foo" == "foo"# => true
Filip Bartuzi

44

เพียงเพื่อแสดงบางสิ่งที่กล่าวถึงในคำตอบ:

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+ เท่า
melvynkim

33

สัญลักษณ์เป็นวิธีการแสดงสตริงและชื่อในทับทิม

ความแตกต่างที่สำคัญระหว่างสัญลักษณ์และสตริงคือสัญลักษณ์ที่มีชื่อเดียวกันนั้นจะถูกกำหนดค่าเริ่มต้นและมีอยู่ในหน่วยความจำเพียงครั้งเดียวในระหว่างเซสชันของทับทิม

มีประโยชน์เมื่อคุณต้องการใช้คำเดียวกันเพื่อแสดงสิ่งต่าง ๆ


19

มีบางคำพูดจากหนังสือAgile Web Development with Railsที่มีชื่อเสียงซึ่งอาจเป็นประโยชน์ในการทำความเข้าใจสัญลักษณ์เช่นกัน:

Rails ใช้สัญลักษณ์เพื่อระบุสิ่งต่าง ๆ โดยเฉพาะอย่างยิ่งมันใช้เป็นคีย์เมื่อตั้งชื่อพารามิเตอร์เมธอดและค้นหาสิ่งต่างๆในแฮช

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

คุณสามารถนึกถึงสัญลักษณ์เป็นตัวอักษรสตริงที่สร้างเป็นค่าคงที่ได้อย่างน่าอัศจรรย์ หรือคุณสามารถพิจารณาเครื่องหมายทวิภาคเพื่อหมายถึง "สิ่งที่มีชื่อ" ดังนั้น: id คือ "สิ่งที่ชื่อว่า id"


5

ในทับทิมแต่ละวัตถุมีตัวระบุวัตถุที่ไม่ซ้ำกันถ้าคุณเขียนputs "hello".object_idใน irb ของคุณและกดปุ่มย้อนกลับ 2 ครั้งคุณจะได้รับ 2 ค่าที่แตกต่างกัน แต่ถ้าคุณเขียน:hello.object_id2 ครั้งคุณจะได้รับผลตอบแทนที่เท่ากัน ที่ควรอธิบายความแตกต่าง


โดยพื้นฐานแล้วผู้ดำเนินการลำไส้ใหญ่มีไว้เพื่อกำหนดสัญลักษณ์
Cesar Jr Rodriguez

2

หากคุณใช้งาน:foo => barฟูจะเป็นสัญลักษณ์ ประโยชน์ของสัญลักษณ์คือมีความเป็นเอกลักษณ์ hash[:foo]เมื่อคุณเรียกรายการในกัญชาที่คุณทำ

สัญลักษณ์ต้องการหน่วยความจำน้อยกว่าสตริงซึ่งทำให้มีประโยชน์หากคุณต้องการทำให้โปรแกรมของคุณเร็วขึ้นเล็กน้อย


0

มันเป็นสัญลักษณ์ โดยทั่วไปคุณจะบอกว่าทั้งสององค์ประกอบของกัญชามีกุญแจblaและbloopมากที่สุดเท่าที่ถ้าคุณได้ใช้สายและ"bla" "bloop"อย่างไรก็ตามมันใช้หน่วยความจำน้อยกว่าสตริงและพิมพ์ได้ง่ายกว่า


0

คำตอบทั้งหมดเหล่านี้จะละเว้นรายละเอียดยั่วเย้าพิเศษ .. หากคุณสร้างสัญลักษณ์: 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 .. มันเป็นคำตอบที่รูบี้ของคำว่า 'เปล่า'


-1

หากคุณคุ้นเคยกับ Java คุณอาจทราบว่า Strings ใน Java นั้นไม่เปลี่ยนรูป สัญลักษณ์นั้นมีความคล้ายคลึงกันใน Ruby พวกมันไม่เปลี่ยนรูปกล่าวคือจำนวนครั้งของสัญลักษณ์เฉพาะใด ๆ:symbolจะแมปกับที่อยู่หน่วยความจำเดียวเท่านั้น และดังนั้นจึงแนะนำให้ใช้สัญลักษณ์ทุกที่ที่เป็นไปได้เนื่องจากจะปรับการใช้หน่วยความจำให้เหมาะสมที่สุด


1
ความจริงที่ว่าสัญลักษณ์นั้นไม่สามารถเปลี่ยนแปลงได้ทำให้มั่นใจได้ว่าพวกมันจะเป็นอินสแตนซ์เดียวกันตลอดทั้งแอปพลิเคชันของคุณและดังนั้นจึงรับประกันได้ว่ามันจะเป็นวัตถุเดียวกัน ตรวจสอบการอ้างอิงเหล่านี้: troubleshooters.com/codecorn/ruby/symbols.htm robertsosinski.com/2009/01/11/... คุณจะได้พบกับโหลดมากขึ้นถ้าคุณ google
Dhruva Sagar

ฉันกำลังพูดถึงการเปรียบเทียบของคุณกับ Java Java Strings ไม่เหมือนกับสัญลักษณ์ สตริงตัวอักษร Java แต่ไม่ใช่สตริงทั้งหมด
smartnut007

คำพูดของฉันอาจไม่ชัดเจนเพียงพอ พวกเขามีความคล้ายคลึงกันเท่านั้นที่เกี่ยวกับความจริงที่ว่าพวกเขาไม่เปลี่ยนรูป
Dhruva Sagar

@DhruvaSagar: การเปรียบเทียบจะดีกว่าถ้าคุณใช้ในวัตถุประสงค์ของ NSStringC "foo"จะมีค่าเสมอ"foo"เนื่องจากสตริงภายในที่เหมือนกันนั้นเพิ่งถูกชี้ไป คำตอบก็ยังคงสับสนอยู่
Rafael Bugajewski
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.