Toán tử ruột kết trong Ruby là gì?


234

Khi tôi nói { :bla => 1, :bloop => 2 }, chính xác những gì :làm? Tôi đã đọc ở đâu đó về cách nó tương tự như một chuỗi, nhưng bằng cách nào đó là một biểu tượng.

Tôi không quá rõ ràng về khái niệm này, ai đó có thể khai sáng cho tôi không?


1
bản sao có thể có của Hiểu biểu tượng trong Ruby
Mladen Jablanović

7
Hãy thử nhìn vào điều này: Hướng dẫn về Biểu tượng của Ruby_Newbie
Hengjie

Video này cho bạn biết mọi thứ bạn cần biết về các biểu tượng.
totymedli

Câu trả lời:


249

:foolà một biểu tượng có tên là "foo". Các biểu tượng có đặc điểm riêng biệt là bất kỳ hai biểu tượng nào được đặt tên giống nhau sẽ giống hệt nhau:

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

Điều này làm cho việc so sánh hai biểu tượng thực sự nhanh chóng (vì chỉ có một so sánh con trỏ được tham gia, trái ngược với việc so sánh tất cả các ký tự giống như bạn trong một chuỗi), cộng với việc bạn sẽ không có hàng triệu bản sao của cùng một biểu tượng.

Ngoài ra, không giống như chuỗi, biểu tượng là bất biến.


2
chỉ tự hỏi tại sao chuỗi ký tự không hỗ trợ thực tập chuỗi?
onmyway133

5
@ onmyway133 Vì chuỗi của Ruby có thể thay đổi. Thực tập chỉ áp dụng cho các giá trị bất biến.
Chris Jester-Young

3
a) Tại sao "foo".equal? "foo"sai? b) Bạn có thể đề cập đến một biểu tượng ở bất cứ đâu, về cơ bản làm cho chúng giống như các biến toàn cầu?
Arc676

2
@ Arc676 1. equal?trong Ruby không so sánh danh tính. Mỗi chuỗi ký tự, như "foo", tạo ra một thể hiện chuỗi mới. Nó hoạt động theo cách đó bởi vì các chuỗi trong Ruby có thể thay đổi. 2. Biểu tượng là toàn cục, nhưng giống các hằng số toàn cầu hơn các biến toàn cục, vì các biểu tượng không có trạng thái. Do đó, việc sử dụng các ký hiệu không phải là một phản mẫu theo cách các biến toàn cục.
Chris Jester-Young

2
@ Arc676 "foo" == "foo"# => đúng
Filip Bartuzi

44

Chỉ để chứng minh một số điều được đề cập trong các câu trả lời:

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

Chạy nó đầu ra:

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

Vì vậy, việc so sánh một chuỗi với một chuỗi sử dụng equal?không thành công vì chúng là các đối tượng khác nhau, ngay cả khi chúng có cùng nội dung. ==so sánh nội dung và kiểm tra tương đương với các biểu tượng nhanh hơn nhiều.

                 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)

Cả hai bài kiểm tra biểu tượng về cơ bản đều giống như tốc độ. Sau 1.000.000 lần lặp lại, chỉ có 0,004733 giây khác nhau, vì vậy tôi muốn nói rằng đó là một sự thay đổi giữa việc sử dụng.


Vô cùng hữu ích! Trên hệ thống của tôi, ==kết quả nhanh hơn so .equal?với cả so sánh chuỗi và ký hiệu. So sánh biểu tượng cho kết quả nhanh hơn 3 lần so với so sánh chuỗi.
melvynkim

33

Biểu tượng là một cách để thể hiện chuỗi và tên trong ruby.

Sự khác biệt chính giữa các ký hiệu và chuỗi là các ký hiệu cùng tên được khởi tạo và tồn tại trong bộ nhớ chỉ một lần trong một phiên của ruby.

Chúng rất hữu ích khi bạn cần sử dụng cùng một từ để thể hiện những thứ khác nhau


19

Có một số trích dẫn từ cuốn sách nổi tiếng Agile Web Development with Rails , có thể hữu ích để hiểu biểu tượng này :

Rails sử dụng các biểu tượng để xác định sự vật. Cụ thể, nó sử dụng chúng làm khóa khi đặt tên các tham số của phương thức và tìm kiếm mọi thứ trong băm.

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

Bạn có thể nghĩ về các biểu tượng như các chuỗi ký tự được tạo thành các hằng số. Ngoài ra, bạn có thể coi dấu hai chấm có nghĩa là "vật được đặt tên", vì vậy: id là "vật có tên id".


5

Trong ruby, mỗi đối tượng có một mã định danh đối tượng duy nhất, nếu bạn viết puts "hello".object_idvào irb của mình và nhấn return trong 2 lần khác nhau, bạn sẽ nhận được 2 giá trị trả về khác nhau, nhưng nếu bạn viết :hello.object_id2 lần, bạn sẽ chỉ nhận được cùng một giá trị trả về. Điều đó nên đã giải thích sự khác biệt.


Về cơ bản toán tử đại tràng là để gán một biểu tượng
Cesar Jr Rodriguez

2

Nếu bạn sử dụng :foo => bar, foo sẽ là một biểu tượng. Lợi ích cho các biểu tượng là chúng là duy nhất. Khi bạn gọi một mục trong hàm băm, bạn làm hash[:foo].

Các biểu tượng đòi hỏi ít bộ nhớ hơn các chuỗi, điều này cũng làm cho chúng hữu ích nếu bạn muốn làm cho chương trình của mình nhanh hơn một chút.


0

Đó là một biểu tượng. Về cơ bản, bạn đang nói rằng hai phần tử của hàm băm có các khóa blabloop, giống như bạn đã sử dụng các chuỗi "bla""bloop". Tuy nhiên, chúng chiếm ít bộ nhớ hơn chuỗi và dễ gõ hơn.


0

Tất cả những câu trả lời này đều bỏ qua một chi tiết trêu ngươi thêm .. nếu bạn xâu chuỗi ký hiệu: foo, bạn sẽ nhận được .. đoán xem .. chuỗi "foo". Vì thế

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>

Do đó .. đối với các lập trình viên Perl .. đó là câu trả lời của Ruby cho 'từ trần'.


-1

Nếu bạn quen thuộc với Java, bạn có thể biết rằng Chuỗi trong Java là bất biến. Các biểu tượng tương tự theo nghĩa đó trong Ruby. Chúng là bất biến, tức là, bất kỳ số lần xuất hiện nào của một biểu tượng cụ thể :symbolsẽ ánh xạ tới chỉ một địa chỉ bộ nhớ. Và, do đó, nên sử dụng các ký hiệu bất cứ khi nào có thể vì nó tối ưu hóa việc sử dụng bộ nhớ.


1
Thực tế là các biểu tượng là bất biến đảm bảo rằng chúng luôn luôn là cùng một thể hiện trong ứng dụng của bạn và do đó chúng được đảm bảo là cùng một đối tượng. Kiểm tra các tài liệu tham khảo: troubleshooters.com/codecorn/ruby/symbols.htm robertsosinski.com/2009/01/11/... Bạn sẽ tìm thấy tải hơn nếu bạn google.
Dhruva Sagar

Tôi đang nói về sự tương tự của bạn với Java. Chuỗi Java không giống với các ký hiệu. Chuỗi ký tự Java là nhưng không phải tất cả các chuỗi.
smartnut007

Có lẽ tuyên bố của tôi không đủ rõ ràng. Chúng tương tự nhau chỉ liên quan đến thực tế là chúng bất biến.
Dhruva Sagar

@DhruvaSagar: Sự tương tự sẽ tốt hơn nếu bạn sử dụng Objective C's NSString. Sẽ "foo"luôn luôn bằng nhau "foo", bởi vì các chuỗi bên trong giống nhau được chỉ vào. Câu trả lời vẫn sẽ gây nhầm lẫn.
Rafael Bugajewski
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.