เวลาทำ iteration บน arrays มี shorthand ชิ้นหนึ่งที่ผมใช้บ่อยมาก คือ trick &: หรือเรียกว่า "ampersand colon" หรือ "pretzel colon" ถ้ายังไม่คุ้นเคย ดูตัวอย่างได้เลย:
words = ["would", "you", "like", "to", "play", "a", "game?"] # นี้... words.map &:length # ..เทียบเท่ากับนี้: words.map { |w| w.length }
จนเมื่อเร็วๆ นี้ ผมคิดว่า &: syntax เป็น operator แต่จริงๆ มันไม่ใช่ มันคือ clever hack ที่เริ่มจาก ActiveSupport และกลายเป็น feature อย่างเป็นทางการใน Ruby 1.8.7
Operator &
นอกจากใช้ทำ AND logic operations แล้ว ตัวอักษร "&" ใน Ruby มีอีกหน้าที่ คือเมื่อวางไว้หน้า method argument มันจะเรียก to_proc บน operand และส่งผ่านเป็น block ค่อนข้างลำบาก อ่านตัวอย่างง่ายกว่า:
def my_method(&block) block.call end class Greeter def self.to_proc Proc.new { "hello" } end end my_method(&Greeter) # returns "hello"
Symbol#to_proc
คุณสามารถเพิ่ม method to_proc ให้ object ใดๆ รวมถึง Symbol นั่นคือสิ่งที่ Ruby ทำเพื่อให้ shortcut &: ทำงาน โค้ดประมาณนี้:
class Symbol def to_proc Proc.new do |item| item.send self end end end
เข้าใจไหม? ส่วนสำคัญคือ item.send(self) self ในที่นี้คือ symbol นั้นเอง
รวมกันดู
Enumerable methods เช่น each และ map รับ block สำหรับแต่ละ item จะเรียก block และส่ง reference ของ item ไป block ในที่นี้ถูกสร้างโดยการเรียก to_proc บน symbol
# &:name evaluates to a Proc, which does item.send(:name) items.map(&:name)
น่าสนใจที่ map ไม่รู้เลยว่ามีอะไรเกิดขึ้น! งานหนักทำโดย symbol :name มันชาญฉลาด...เกือบเกินไป แต่เป็นส่วนหนึ่งของ standard library มาหลายปีแล้ว และสะดวกมากจนผมคิดว่าไม่หยุดใช้แน่ๆ :)