Computer >> Máy Tính >  >> Lập trình >> Ruby

Thủ thuật thông minh làm cho `items.map (&:name)` hoạt động

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ư eachmap 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ờ. :)