J
Joel VanderWerf
Here is an amusing little control structure that shows off ruby's
continuations and is actually useful (of course, you might want to use
something other than a global variable--that's just for simplicity):
# Yield to the associated block, if any. If the block raises an
# exception that matches +excep+, then resume execution at the
# previous successful fallback block.
#
def fallback(excep = StandardError)
cont = nil
callcc {|cont|}
result = block_given? ? yield : nil
$cont = cont # if it worked, remember what we did
result
rescue excep
$cont.call if $cont
raise
end
if __FILE__ == $0
first_time_C = true
first_time_E = true
puts "A"
fallback do
puts "B"
end
fallback do
puts "C"
if first_time_C
first_time_C = false
raise
end
end
fallback do
puts "D"
end
fallback do
puts "E"
if first_time_E
first_time_E = false
raise
end
end
fallback do
puts "F"
end
end
__END__
Output is:
A
B
C
B
C
D
E
D
E
F
continuations and is actually useful (of course, you might want to use
something other than a global variable--that's just for simplicity):
# Yield to the associated block, if any. If the block raises an
# exception that matches +excep+, then resume execution at the
# previous successful fallback block.
#
def fallback(excep = StandardError)
cont = nil
callcc {|cont|}
result = block_given? ? yield : nil
$cont = cont # if it worked, remember what we did
result
rescue excep
$cont.call if $cont
raise
end
if __FILE__ == $0
first_time_C = true
first_time_E = true
puts "A"
fallback do
puts "B"
end
fallback do
puts "C"
if first_time_C
first_time_C = false
raise
end
end
fallback do
puts "D"
end
fallback do
puts "E"
if first_time_E
first_time_E = false
raise
end
end
fallback do
puts "F"
end
end
__END__
Output is:
A
B
C
B
C
D
E
D
E
F