Computer >> คอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

แฮ็คที่ชาญฉลาดที่ทำให้ `items.map(&:name)` ทำงานได้

เมื่อวนซ้ำอาร์เรย์ มีชวเลขชิ้นหนึ่งที่ฉันพบว่าตัวเองใช้ซ้ำแล้วซ้ำอีก นี่คือเคล็ดลับ &:หรือที่รู้จักว่า "เครื่องหมายโคลอน" หรือ "โคลอนเพรทเซล" ในกรณีที่คุณไม่คุ้นเคย วิธีทำงานมีดังนี้

words = ["would", "you", "like", "to", "play", "a", "game?"]

# this...
words.map &:length

# ..is equivalent to this:
words.map { |w| w.length }

จนกระทั่งเมื่อไม่นานมานี้ ฉันได้สันนิษฐานว่าไวยากรณ์ &:เป็นโอเปอเรเตอร์ แต่มันไม่ใช่ เป็นแฮ็คที่ชาญฉลาดที่เริ่มต้นใน ActiveSupport และกลายเป็นคุณสมบัติอย่างเป็นทางการใน Ruby 1.8.7

ตัวดำเนินการ &

นอกจากจะใช้สำหรับการดำเนินการตรรกะ AND แล้ว อักขระ "&" ​​ยังมีการใช้งานอื่นใน Ruby เมื่อเพิ่มไปที่จุดเริ่มต้นของอาร์กิวเมนต์เมธอด จะเรียก to_proc บนตัวถูกดำเนินการและส่งผ่านเป็นบล็อก นั่นเป็นคำหนึ่ง ง่ายกว่ามากในการดูตัวอย่าง:

def my_method(&block)
  block.call
end

class Greeter
  def self.to_proc
    Proc.new { "hello" }
  end
end

my_method(&Greeter) # returns "hello"

สัญลักษณ์#to_proc

คุณสามารถเพิ่ม to_proc วิธีการไปยังวัตถุใด ๆ รวมทั้งสัญลักษณ์ นั่นคือสิ่งที่ ruby ​​ทำเพื่อให้ &: ทางลัด หน้าตาประมาณนี้:

class Symbol
  def to_proc
    Proc.new do |item|
      item.send self
    end
  end
end

ใสเหมือนโคลน? ส่วนที่สำคัญคือ item.send(self) . ตนเอง ในกรณีนี้ หมายถึง สัญลักษณ์

รวมทุกอย่างเข้าด้วยกัน

วิธีการมากมายเช่น each และ map ยอมรับบล็อก สำหรับแต่ละรายการพวกเขาเรียกบล็อกและส่งการอ้างอิงไปยังรายการ บล็อกในกรณีนี้ถูกสร้างขึ้นโดยการเรียก to_proc บนสัญลักษณ์

# &:name evaluates to a Proc, which does item.send(:name)
items.map(&:name)

สิ่งที่น่าสนใจเกี่ยวกับเรื่องนี้ก็คือ map ไม่รู้ว่าสิ่งนี้กำลังเกิดขึ้น! งานส่วนใหญ่กำลังทำโดย :name เครื่องหมาย. มันฉลาดมาก...เกือบจะฉลาดเกินกว่าจะชอบใจฉันแล้ว แต่ตอนนี้มันเป็นส่วนหนึ่งของไลบรารีมาตรฐานของ Ruby มาหลายปีแล้ว และมันก็สะดวกมาก ฉันสงสัยว่าฉันจะหยุดใช้มันไปก่อน :)