זהירות: תפיסת חריג מבלוק ברובי
03/04/2026
הקוד הבא ברובי זורק Exception מתוך הלולאה ותופס אותה, וקל לראות שזה עובד:
begin
[1, 2, 3].each do |i|
raise 'Stop' if i.even?
end
rescue => e
puts "Error: #{e.message}"
end
אבל חשוב לא להתבלבל, המבנה של rescue אחרי בלוק לא מבטיח שכל Exception שייזרק מהבלוק באמת ייתפס. הדוגמה הקלאסית היא קוד שנשלח להרצה ב Thread נפרד, וזה נראה ככה:
class Array
def pmap(&block)
each do |i|
Thread.new { block.call(i) }
end
self
end
end
begin
[1, 2, 3].pmap do |i|
raise 'Stop' if i.even?
end
rescue => e
puts "Error: #{e.message}"
end
פונקציית pmap שהגדרתי על Array שולחת את הבלוק לרוץ ב thread נפרד ולכן ה Exception שהבלוק זורק לא נתפס ב Thread הראשי. דרך אחת לטפל בקוד כזה היא להקפיד להעביר את ה Exception ל Thread הראשי מתוך pmap, כלומר:
class Array
def pmap(&block)
threads = each.map do |i|
Thread.new do
block.call(i)
end
end
threads.each(&:join)
threads.each(&:value)
end
end
והפעם הפעלה תדפיס את השגיאה:
#<Thread:0x000000012233cbd8 a.rb:4 run> terminated with exception (report_on_exception is true):
a.rb:15:in `block in <main>': Stop (RuntimeError)
from a.rb:5:in `block (2 levels) in pmap'
Error: Stop