contine after exception

J

junkone

How do i continue a loop after a exception? It actually captures the
exception . How do i get the exception handler to start executing from
4 to call the printstuff function?


def printStuff(inpu) ## just print stuff
puts "printing" + inpu.to_s
if (inpu==3)
raise RetryException.new(true)
end
# raise RuntimeError
end
def enter1
begin
[1,2,3,4,5,6,7,8].each{|value| printStuff(value)}#call function
to print.


rescue RetryException

puts " inside rescuedo nothing"
###QUESTION: how to continue calling
#puts dd.okToRetry

rescue
puts "other exception"
ensure
puts "insode ensire"
end
end
end
 
B

Brian Schröder

How do i continue a loop after a exception? It actually captures the
exception . How do i get the exception handler to start executing from
4 to call the printstuff function?


def printStuff(inpu) ## just print stuff
puts "printing" + inpu.to_s
if (inpu==3)
raise RetryException.new(true)
end
# raise RuntimeError
end
def enter1
begin
[1,2,3,4,5,6,7,8].each{|value| printStuff(value)}#call function
to print.


rescue RetryException

puts " inside rescuedo nothing"
###QUESTION: how to continue calling
#puts dd.okToRetry

rescue
puts "other exception"
ensure
puts "insode ensire"
end
end
end

Try with

(1..8).each do | value |
begin
raise "Exception" if value == 3
puts value
rescue
puts "That was exceptional"
end
end

cheers,

Brian
 
C

Csaba Henk

How do i continue a loop after a exception? It actually captures the
exception . How do i get the exception handler to start executing from
4 to call the printstuff function?


def printStuff(inpu) ## just print stuff
puts "printing" + inpu.to_s
if (inpu==3)
raise RetryException.new(true)
end
# raise RuntimeError
end
def enter1
begin
[1,2,3,4,5,6,7,8].each{|value| printStuff(value)}#call function
to print.


rescue RetryException

puts " inside rescuedo nothing"
###QUESTION: how to continue calling
#puts dd.okToRetry

rescue
puts "other exception"
ensure
puts "insode ensire"
end
end
end

Do you think of something like this?

#############################################

module Exception::Continuable

def try &bl
bl.call
rescue Exception => exp
callcc do |cc|
exp.instance_variable_set :mad:continuation, cc
exp.instance_variable_set :mad:binding, bl
class << exp
attr_reader :continuation, :binding
def continue
@continuation.call
end
end
raise exp
end
end

end

class Object
include Exception::Continuable
end

class RetryException < Exception
end

def printStuff(inpu) ## just print stuff
puts "printing" + inpu.to_s
if inpu == 3
raise RetryException
end
end

begin
[1,2,3,4,5,6,7,8].each{|value| try do printStuff(value) end }
rescue RetryException => err
puts " inside rescuedo nothing"
err.continue
rescue
puts "other exception"
ensure
puts "insode ensire"
end

===========>

printing1
printing2
printing3
inside rescuedo nothing
printing4
printing5
printing6
printing7
printing8
insode ensire


#############################################


Regards,
Csaba
 
M

Morton Goldberg

I think I understand most of what you are doing here, and I think
it's very nice. The one point that eludes me is purpose of the line:

exp.instance_variable_set :mad:binding, bl

Could you explain that. The code seems to work just fine even when
that line is commented out.

Regards, Morton
 
C

Csaba Henk

I think I understand most of what you are doing here, and I think
it's very nice. The one point that eludes me is purpose of the line:

exp.instance_variable_set :mad:binding, bl

Could you explain that. The code seems to work just fine even when
that line is commented out.

Yeah, it's irrelevant as far as the actual problem is considered.
However, I wanted to make Exception::Continuable generic (in fact, I
have already had it at hand).

It seems to be handy to be able to examine the situation where the
badness happened, so that we can decide if we really want to continue
from after the exception or let just abort that branch.

Having access to the bindings of the location where the exception has been
raised can help you in that analysis.

Regards,
Csaba
 
M

Morton Goldberg

Thanks, I think I understand now. And I agree that having access to
the local variables of the try block is a Really Good Thing.

But don't you think it would be clearer if you called the accessor
"block" rather than "binding". After all, its a Proc object not a
Binding object that's returned by err.binding. To actually get at the
value of the block variable, one has to apply Proc#binding to what
err.binding returns, giving err.binding.binding, which I find
somewhat confusing. I think code using your continuable exception
would read better with err.block.binding. See modified code below.

Regards, Morton

module Exception::Continuable

def try &bl
bl.call
rescue Exception => exp
callcc do |cc|
exp.instance_variable_set:)@continuation, cc)
exp.instance_variable_set:)@block, bl) # change
class << exp
attr_reader :continuation, :block # change
def continue
@continuation.call
end
end
raise exp
end
end

end

# ...

begin
[1,2,3,4,5,6,7,8].each{|v| try do printStuff(v) end}
rescue RetryException => err
puts "inside retry rescue"
what = eval('v', err.block.binding) # new
puts "try block working on #{what}" # new
puts "going back to try block" # new
err.continue
rescue
puts "other exception"
ensure
puts "inside ensure"
end

which produces

printing 1
printing 2
printing 3
inside retry rescue
try block working on 3
going back to try block
printing 4
printing 5
printing 6
printing 7
printing 8
inside ensure
 
C

Csaba Henk

Thanks, I think I understand now. And I agree that having access to
the local variables of the try block is a Really Good Thing.

But don't you think it would be clearer if you called the accessor
"block" rather than "binding". After all, its a Proc object not a
Binding object that's returned by err.binding. To actually get at the
value of the block variable, one has to apply Proc#binding to what
err.binding returns, giving err.binding.binding, which I find
somewhat confusing. I think code using your continuable exception
would read better with err.block.binding. See modified code below.


Well, you don't have to write err.binding.binding, because a proc
can be used as a binding as-is:

def foo &bl
eval "x", bl
end

x = 5

foo {} ==> 5

Yet it's true that a proc has more in it than a binding, moreover we can make
use of this extra in the context of continuable exceptions -- eg., after
some kind of sanitization we might retry the "try" guarded action by
calling the block. That wouldn't happen if we just continued from the
error.

So, yes, eventually I argree that it's better to call that block
"block".

Regards,
Csaba
 
M

Morton Goldberg

Well, you don't have to write err.binding.binding, because a proc
can be used as a binding as-is:

I didn't know that (obviously :), but now that I've looked it up in
the Pickaxe book, I see that it's mentioned. Is that behavior new to
1.8? Or is it Proc#binding that's new?

Although I find your try with a continuable exception a fine example
of something can be done rather easily in Ruby that would be
difficult or impossible in most other programming languages, I think
it's more. I think it's likely I'll put it to practical use some day.
Thanks again.

There is a lot about Ruby I've yet to learn. This thread has been
very educational for me.

Regards, Morton
 

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

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top