Break Proc ใน Ruby
เชื่อว่าหลายคนน่าจะเคยได้ยินคำว่า Guard Clause ซึ่งเป็นรูปแบบหนึ่งในการเขียนโปรแกรมที่ ที่ฟังก์ชั่นจะทำการเช็ค เงื่อนไขบางอย่างก่อนที่จะเข้ากระบวนการ process ถ้าไม่ตรงตามเงื่อนไข ก็จะถีบออกจากฟังก์ชั่นไป เช่น ถ้าเราต้องการจะรัน process ที่ รับค่าเฉพาะจำนวนเต็มบวกเท่านั้นก็จะเขียนประมาณนี้
def process(input)
return if input < 1 .
.
.
end
ซึ่งท่านี้ ก็ช่วยลดความซับซ้อนในการใช้ if-clause หลายๆชั้น ทำให้อ่านโค้ดได้ง่ายขึ้น
ทีนี้ก็เข้ามาสู่ปัญหากัน คือ ตอนนี้ส่วนตัวมีการใช้ event stream ผ่าน Nats-streaming ซึ่งเราก็จะประกาศการ subscribe event แล้วก็เรียกใช้ block/proc ตาม event ที่เกิดขึ้น เช่น
stan.subscribe 'event1' do |msg|
data= JSON.parse(msg.data, symbolize_names: true)
break unless data[:id].is_a? Integer .
.
.
end
ทีนี้ก็พบปัญหา ว่ามันเกิด error ประหลาดๆ เมื่อเราลองค่าที่มันไม่ใช่ไป
break from proc-closure (LocalJumpError)
เลยต้องไปนั่งดูข้อมูลเพิ่มเติมสักหน่อย แล้วก็พบว่า
Proc ใน ruby จะประกอบด้วย 2 ลักษณะคือ Proc กับ Lambda ซึ่งตัว Lambda อาจจะมีความเข้มงวดมากกว่า Proc แต่ก็ทำให้ block ใน Lambda มีความใกล้เคียงกับ function
ซึ่งในการ ใช้งาน keyword break ก็จะส่งผลไม่เหมือนกัน
โดยเมื่อเราใช้ break ของ proc มันจะกระโดดออกมาถึง function ภายนอกมัน แต่ถ้าภายนอก block ไม่มี method คลุมอยู่ มันก็จะเกิด error แบบที่เห็นได้
แต่ถ้าเป็น Lambda ตัว break จะจบที่ lambda นั้น
ทีนี้กลับมาที่เรื่องนี้ เราจะแก้ไขยังไงต่อดี
ก็พบว่า มันก็มีอีกทางเลือก ที่ใช้สำหรับ skip ส่วนอื่นจนจบ block ซึ่งเป็นตามวัตถุประสงค์ที่เราต้องการ
ในที่นี้คือ keyword “next”
ดังนั้นเราก็เปลี่ยนจาก break เป็น next สำหรับกรณีนี้ก็จะแก้ปัญหาได้
stan.subscribe 'event1' do |msg|
data= JSON.parse(msg.data, symbolize_names: true)
next unless data[:id].is_a? Integer .
.
.
end
ซึ่งถามว่าแก้ได้ทุกกรณีไหม อาจจะไม่ แต่สำหรับเคสนี้ ซึ่งไม่มี method คลุมตัว block นี้ไว้ แล้วเราอยากให้มันจบ callback ถ้า ข้อมูลมันผิด ท่านี้สามารถตอบโจทย์ได้