Khi lặp lại các mảng, có một phần viết tắt mà tôi thấy mình sử dụng đi sử dụng lại nhiều lần. Đó là thủ thuật &:, hay còn gọi là "dấu và hai chấm" hoặc "dấu hai chấm bánh quy". Trong trường hợp bạn không quen với nó, đây là cách nó hoạt động:
words = ["would", "you", "like", "to", "play", "a", "game?"]
# this...
words.map &:length
# ..is equivalent to this:
words.map { |w| w.length }
Cho đến gần đây, tôi đã giả định rằng cú pháp &:là một toán tử. Nhưng nó không phải. Đó là một bản hack thông minh bắt đầu từ ActiveSupport và trở thành một tính năng chính thức trong Ruby 1.8.7.
Toán tử &
Ngoài việc được sử dụng cho các phép toán logic AND, ký tự "&" còn có một công dụng khác trong Ruby. Khi được thêm vào đầu đối số phương thức, nó gọi to_proc trên toán hạng của nó và chuyển nó vào dưới dạng một khối. Đó là một cái miệng. Thật đơn giản hơn nhiều để xem ví dụ:
def my_method(&block)
block.call
end
class Greeter
def self.to_proc
Proc.new { "hello" }
end
end
my_method(&Greeter) # returns "hello"
Ký hiệu # to_proc
Bạn có thể thêm to_proc
đối với bất kỳ đối tượng nào, bao gồm cả Biểu tượng. Đó chính xác là những gì ruby làm để cho phép &:
đường tắt. Nó trông giống như sau:
class Symbol
def to_proc
Proc.new do |item|
item.send self
end
end
end
Trong như bùn? Phần quan trọng là item.send(self)
. Bản thân, trong trường hợp này là biểu tượng.
Tập hợp tất cả lại với nhau
Các phương thức có thể thực thi như each
và map
chấp nhận một khối. Đối với mỗi mục, họ gọi khối và chuyển nó một tham chiếu đến mục đó. Khối trong trường hợp này được tạo bằng cách gọi to_proc trên biểu tượng.
# &:name evaluates to a Proc, which does item.send(:name)
items.map(&:name)
Điều thú vị về điều này là map
không biết bất kỳ điều này đang xảy ra! Phần lớn công việc đang được thực hiện bởi :name
Biểu tượng. Nó chắc chắn là thông minh ... gần như quá thông minh so với sở thích của tôi. Nhưng nó đã là một phần của thư viện tiêu chuẩn của Ruby trong nhiều năm tại thời điểm này, và nó rất tiện dụng, tôi nghi ngờ rằng tôi sẽ ngừng sử dụng nó ngay bây giờ. :)