เมื่อฉันพูด{ :bla => 1, :bloop => 2 }
สิ่งที่ว่าจะ:
ทำอย่างไร ฉันอ่านบางที่เกี่ยวกับความคล้ายคลึงกับสตริง แต่อย่างใดสัญลักษณ์
ฉันไม่ชัดเจนในแนวคิดนี้ใครจะช่วยสอนฉันได้บ้าง
เมื่อฉันพูด{ :bla => 1, :bloop => 2 }
สิ่งที่ว่าจะ:
ทำอย่างไร ฉันอ่านบางที่เกี่ยวกับความคล้ายคลึงกับสตริง แต่อย่างใดสัญลักษณ์
ฉันไม่ชัดเจนในแนวคิดนี้ใครจะช่วยสอนฉันได้บ้าง
คำตอบ:
:foo
เป็นสัญลักษณ์ที่ชื่อว่า "foo" สัญลักษณ์มีคุณสมบัติที่แตกต่างกันซึ่งสัญลักษณ์สองชื่อที่เหมือนกันจะเหมือนกัน:
"foo".equal? "foo" # false
:foo.equal? :foo # true
สิ่งนี้ทำให้การเปรียบเทียบสัญลักษณ์สองตัวนั้นเร็วมาก (เนื่องจากมีการเปรียบเทียบตัวชี้เท่านั้นซึ่งต่างจากการเปรียบเทียบอักขระทั้งหมดที่คุณต้องการในสตริง) และคุณจะไม่มีสำเนาเดียวกันที่มีสัญลักษณ์พันล้านตัวที่ลอยอยู่
นอกจากนี้ยังแตกต่างจากสตริงสัญลักษณ์ที่ไม่เปลี่ยนรูป
"foo".equal? "foo"
เท็จ b) คุณสามารถอ้างถึงสัญลักษณ์ได้ทุกที่ทำให้พวกเขาเป็นเหมือนตัวแปรทั่วโลก?
equal?
ใน Ruby ทำการเปรียบเทียบตัวตน สตริงแต่ละตัวอักษรเช่น"foo"
สร้างสตริงอินสแตนซ์ใหม่ มันทำงานได้อย่างนั้นเพราะสตริงใน Ruby นั้นไม่แน่นอน 2. สัญลักษณ์เป็นโลก แต่คล้ายกับค่าคงที่ทั่วโลกมากกว่าตัวแปรทั่วโลกเนื่องจากสัญลักษณ์ไม่มีสถานะ ดังนั้นการใช้สัญลักษณ์ไม่ใช่ปฏิสสารในลักษณะที่ตัวแปรทั่วโลกเป็น
"foo" == "foo"
# => true
เพียงเพื่อแสดงบางสิ่งที่กล่าวถึงในคำตอบ:
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+ เท่า
สัญลักษณ์เป็นวิธีการแสดงสตริงและชื่อในทับทิม
ความแตกต่างที่สำคัญระหว่างสัญลักษณ์และสตริงคือสัญลักษณ์ที่มีชื่อเดียวกันนั้นจะถูกกำหนดค่าเริ่มต้นและมีอยู่ในหน่วยความจำเพียงครั้งเดียวในระหว่างเซสชันของทับทิม
มีประโยชน์เมื่อคุณต้องการใช้คำเดียวกันเพื่อแสดงสิ่งต่าง ๆ
มีบางคำพูดจากหนังสือAgile Web Development with Railsที่มีชื่อเสียงซึ่งอาจเป็นประโยชน์ในการทำความเข้าใจสัญลักษณ์เช่นกัน:
Rails ใช้สัญลักษณ์เพื่อระบุสิ่งต่าง ๆ โดยเฉพาะอย่างยิ่งมันใช้เป็นคีย์เมื่อตั้งชื่อพารามิเตอร์เมธอดและค้นหาสิ่งต่างๆในแฮช
redirect_to :action => "edit", :id => params[:id]
คุณสามารถนึกถึงสัญลักษณ์เป็นตัวอักษรสตริงที่สร้างเป็นค่าคงที่ได้อย่างน่าอัศจรรย์ หรือคุณสามารถพิจารณาเครื่องหมายทวิภาคเพื่อหมายถึง "สิ่งที่มีชื่อ" ดังนั้น: id คือ "สิ่งที่ชื่อว่า id"
ในทับทิมแต่ละวัตถุมีตัวระบุวัตถุที่ไม่ซ้ำกันถ้าคุณเขียนputs "hello".object_id
ใน irb ของคุณและกดปุ่มย้อนกลับ 2 ครั้งคุณจะได้รับ 2 ค่าที่แตกต่างกัน แต่ถ้าคุณเขียน:hello.object_id
2 ครั้งคุณจะได้รับผลตอบแทนที่เท่ากัน ที่ควรอธิบายความแตกต่าง
หากคุณใช้งาน:foo => bar
ฟูจะเป็นสัญลักษณ์ ประโยชน์ของสัญลักษณ์คือมีความเป็นเอกลักษณ์ hash[:foo]
เมื่อคุณเรียกรายการในกัญชาที่คุณทำ
สัญลักษณ์ต้องการหน่วยความจำน้อยกว่าสตริงซึ่งทำให้มีประโยชน์หากคุณต้องการทำให้โปรแกรมของคุณเร็วขึ้นเล็กน้อย
มันเป็นสัญลักษณ์ โดยทั่วไปคุณจะบอกว่าทั้งสององค์ประกอบของกัญชามีกุญแจbla
และbloop
มากที่สุดเท่าที่ถ้าคุณได้ใช้สายและ"bla"
"bloop"
อย่างไรก็ตามมันใช้หน่วยความจำน้อยกว่าสตริงและพิมพ์ได้ง่ายกว่า
คำตอบทั้งหมดเหล่านี้จะละเว้นรายละเอียดยั่วเย้าพิเศษ .. หากคุณสร้างสัญลักษณ์: 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 .. มันเป็นคำตอบที่รูบี้ของคำว่า 'เปล่า'
หากคุณคุ้นเคยกับ Java คุณอาจทราบว่า Strings ใน Java นั้นไม่เปลี่ยนรูป สัญลักษณ์นั้นมีความคล้ายคลึงกันใน Ruby พวกมันไม่เปลี่ยนรูปกล่าวคือจำนวนครั้งของสัญลักษณ์เฉพาะใด ๆ:symbol
จะแมปกับที่อยู่หน่วยความจำเดียวเท่านั้น และดังนั้นจึงแนะนำให้ใช้สัญลักษณ์ทุกที่ที่เป็นไปได้เนื่องจากจะปรับการใช้หน่วยความจำให้เหมาะสมที่สุด
NSString
C "foo"
จะมีค่าเสมอ"foo"
เนื่องจากสตริงภายในที่เหมือนกันนั้นเพิ่งถูกชี้ไป คำตอบก็ยังคงสับสนอยู่