Exception that doesn't stop program flow

T

Terry Michaels

Okay... this might sound weird (contradictory even) but is there a way
in Ruby to create an exception that can be caught at any level above the
point of origin, but /doesn't/ actually interrupt program flow when it
is raised? In a program I am writing, a certain sort of event occurs
that I have to be sure to deal with later on outside of the function,
but I don't want it to interrupt the function because it will leave
object data inconsistent. I probably just need to write another event
class and pop this onto some kind of global queue; but I thought I might
as well ask in case there is something helpful I have overlooked.
 
J

Jesús Gabriel y Galán

Okay... this might sound weird (contradictory even) but is there a way
in Ruby to create an exception that can be caught at any level above the
point of origin, but /doesn't/ actually interrupt program flow when it
is raised? In a program I am writing, a certain sort of event occurs
that I have to be sure to deal with later on outside of the function,
but I don't want it to interrupt the function because it will leave
object data inconsistent. I probably just need to write another event
class and pop this onto some kind of global queue; but I thought I might
as well ask in case there is something helpful I have overlooked.

If you have to restore the object's integrity after an exceptional
event, you can use an ensure block. An ensure block is always called,
after the correct execution or in light of an exception, before
returning:

def method
puts "in the block"
begin
puts "in the block that raises"
raise "Exception ocurred"
ensure
puts "restoring object integrity"
end
end

begin
method
rescue
puts "rescuing the exception"
end

Here you handle everything you need to do to safely return from the
method in the ensure block, and the exception will be still raised.

Jesus.
 
A

Avdi Grimm

Okay... this might sound weird (contradictory even) but is there a way
in Ruby to create an exception that can be caught at any level above the
point of origin, but /doesn't/ actually interrupt program flow when it
is raised?

There are a few ways to do this. One way to return side-band data like
this is to set a thread-local variable and check its value later on. A
clean-ish way to do this is to make a method that encapsulates the
error check:

def handle_errors
yield
if Thread.current[:error]
# handle error
Thread.current[:error] = nil
end
end

handle_errors do
# ... code that might set the error flag ...
end
 
J

James M. Lawrence

Terry Michaels wrote in post #981237:
Okay... this might sound weird (contradictory even) but is there a
way in Ruby to create an exception that can be caught at any level
above the point of origin, but /doesn't/ actually interrupt program
flow when it is raised?

When a printer is halfway through a 200-page job and it runs out of
paper, it pauses. When someone feeds it more paper, it continues from
where it left off.

Imagine a printer which, when it ran out of paper, shredded everything
it just printed! "Out of paper," it beeps, as chopped bits of the
previously-perfectly-fine first 100 pages are ejected into the air.

Exceptions behave like the latter case. You lose the running state of
the program--the (possibly deep) stack is lost.

We often want program errors to be handled the way a regular printer
handles them, not the way the above printer/shredder combo does. When
an error occurs, execution should pause while a control panel pops up
awaiting instruction. If the error occurs inside a library, for
example, the library authors are responsible for the control panel.

This kind of multi-stage error-handling was perfected long ago in the
Lisp condition system. The buttons on the control panel are called
restarts and the thing that pushes a button is called a handler.

I ported the condition system to Ruby after I lost the results of an
hours-long running program due to a trivial glitch in the input
data. This Rubified condition system has served me well, though I'm
sure nobody else uses it: http://cond.rubyforge.org
 
A

Avdi Grimm

I ported the condition system to Ruby after I lost the results of an
hours-long running program due to a trivial glitch in the input
data. This Rubified condition system has served me well, though I'm
sure nobody else uses it: http://cond.rubyforge.org

I'm intrigued. I'm in the process of writing an eBook on handling
failures in Ruby (http://avdi.org/devblog/exceptional-ruby/), and just
this morning I finished a section on alternatives to exceptions. I'm
going to have to play with this... it may warrant some coverage in the
book. I've thought for a long time that Ruby could use to borrow some
of Lisp's condition system.
 
B

botp

I'm intrigued. I'm in the process of writing an eBook on handling
failures in Ruby (http://avdi.org/devblog/exceptional-ruby/), and just
this morning I finished a section on alternatives to exceptions. I'm
going to have to play with this... it may warrant some coverage in the
book. I've thought for a long time that Ruby could use to borrow some
of Lisp's condition system.

+1
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top