คำว่า "yield" ใน Ruby หมายถึงอะไร? และมันทำอะไรอย่างแน่ชัด?
จริงๆ แล้ว...
Yield เป็นคีย์เวิร์ด (หมายถึงมันเป็นส่วนหลักของภาษา) และใช้ภายในเมธอดสำหรับเรียกบล็อก (block)
นี่คือสิ่งที่คุณต้องรู้:
- การเรียกบล็อกจะรันโค้ดภายในบล็อกนั้น (เหมือนเรียกเมธอด)
- Yield สามารถส่งอาร์กิวเมนต์จำนวนเท่าไรก็ได้ไปยังบล็อก
- ค่าส่งคืนของบล็อกจะกลายเป็นค่าส่งคืนของ
yield
คุณต้องเข้าใจบล็อก (blocks) เพื่อให้สิ่งนี้เข้าใจได้
คุณสามารถคิดถึงบล็อกได้ว่าเป็นเมธอดที่ไม่มีชื่อ ที่สามารถส่งผ่านเป็นอาร์กิวเมนต์เพิ่มเติมให้เมธอดอื่นๆ
ตัวอย่าง:
def make_salad
yield "lettuce"
yield "carrots"
yield "olive oil"
end
make_salad { |ingredient| puts "Adding #{ingredient} to salad!" }
นี่เรียกบล็อก 3 ครั้ง ผลลัพธ์คือ:
Adding lettuce to salad! Adding carrots to salad! Adding olive oil to salad!
นั่นคือหัวใจของ yield คือเหมือนเรียกเมธอด แตแทนที่จะเรียกเมธอด คุณเรียกบล็อก
เราไม่มีชื่อสำหรับบล็อก ดังนั้นคีย์เวิร์ดนี้จัดการเรื่องนั้น
ตอนนี้:
มาสำรวจว่าจะเกิดอะไรขึ้น หากคุณไม่มีบล็อกให้เรียก
Yield โดยไม่มีบล็อก == ข้อความข้อผิดพลาด
หากคุณเรียก yield โดยไม่มีบล็อก แล้วคุณจะได้ข้อผิดพลาด
ตัวอย่าง:
def write_code yield end write_code # LocalJumpError: no block given (yield)
ข้อผิดพลาดนี้ชัดเจน "no block given" หมายความว่าการเรียกเมธอด write_code ไม่ได้ให้บล็อกมา
คุณสามารถป้องกันข้อผิดพลาดนี้ได้อย่างไร?
แบบนี้:
def write_code yield if block_given? end
เมธอด block_given? ตรวจสอบว่ามีบล็อกให้หรือไม่ และสิ่งนี้อนุญาตให้คุณ yield ก็ต่อเมื่อเป็นจริง
ทำไมต้องใช้ Yield?
การใช้ yield เปิดใช้งานบล็อก
เราใช้บล็อกเพื่อส่งชิ้นส่วนของโค้ดเป็นส่วนหนึ่งของการเรียกเมธอด
นั่นช่วยได้เมื่อ:
- คุณต้องการเขียนฟังก์ชัน logging แบบทั่วไป ที่บันทึกว่าชิ้นโค้ดหนึ่งใช้เวลานานเท่าไร
- คุณต้องการรันโค้ดบางอย่างเมื่อเมธอดเสร็จ (เหมือน "callbacks" ใน Javascript)
- คุณต้องการ "lazy code" โค้ดที่รันก็ต่อเมื่อจำเป็น และสามารถปรับแต่งโดยผู้ใช้ (ตัวอย่างอ่านเกี่ยวกับเมธอด
Hash#fetch)
ดี!
Yield_Self — ความแตกต่างคืออะไร?
คุณอาจพบเมธอด yield_self ใหม่นี้ และคิดว่ามันเกี่ยวข้องกับ yield
จริงๆ แล้ว ไม่เกี่ยวข้อง
แม้ yield(self) ก็แตกต่าง เพราะ self หมายถึงออบเจ็กต์ปัจจุบัน
ที่ yield_self ซึ่งถูกเพิ่มใน Ruby 2.5 หมายถึงออบเจ็กต์ที่เรากำลังเรียกเมธอดอยู่
การใช้งานที่ดีสำหรับเมธอดนี้?
ใช้ทุกครั้งที่คุณต้องการเชนเมธอด (chain methods) และทำบางอย่างกับออบเจ็กต์ที่คุณเรียก yield_self อยู่
ขณะส่งคืนผลลัพธ์ แทนที่จะส่งคืนออบเจ็กต์ต้นฉบับ
ตัวอย่าง:
n_squared = ->(n) { n ** 2 }
2 .yield_self(&n_squared)
.yield_self(&n_squared)
# 16
ใน Ruby 2.6 มีอีเลียส (alias) สำหรับ yield_self คือเมธอด then
แตอย่าสับสนกับ yield ปกติของคุณ
โอเค?
Yield ใน Rails
ผมควรให้การกล่าวถึงการใช้ yield ใน Rails และเทมเพลตเอนจินด้วย
คุณจะพบ yield ภายในเลย์เอาต์ (layouts)
Rails แทนที่มันด้วยเนื้อหาของวิวที่คุณกำลังเรนเดอร์
ไม่มี yield เท่ากับเลย์เอาต์ว่าง!
นั่นคือวิธีที่เลย์เอาต์และวิวของคุณถูกรวมเข้าด้วยกัน
สรุป
คุณได้เรียนรู้เกี่ยวกับคีย์เวิร์ด yield ใน Ruby แล้ว! ทุกอย่างคือ มันคืออะไร ทำงานอย่างไร และทำไมมันสำคัญ
ตอนนี้ลองใช้ในโค้ด Ruby ของคุณดูสิ
ขอบคุณที่อ่าน! 🙂