From: Brian Marick Date: 2001-08-23T17:18:53+09:00 Subject: [ruby-talk:20164] Re: breaking out of nested loops While probably the right way to do this is to use a block... def yield_matches(first_range, next_range) for i in first_range for j in next_range yield i if i == j end end end def find_special_number(first_range, next_range) puts "== Look for a special value in #{first_range} and #{next_range}" yield_matches(first_range, next_range) { | val | puts "Value is #{val.inspect}." if val + val == val * val puts "Isn't that special?" return end } puts "Nothing special here." end if __FILE__ == $0 find_special_number(0..3, 1..5) find_special_number(3..8, 4..7) end % ruby continuation-passing.rb == Look for a special value in 0..3 and 1..5 Value is 1. Value is 2. Isn't that special? == Look for a special value in 3..8 and 4..7 Value is 4. Value is 5. Value is 6. Value is 7. Nothing special here. =================== As I say, while probably the right way to do this is to use a block, the continuation version can be made to work like this: def find_special_number(first_range, next_range) puts "== Look for a special value in #{first_range} and #{next_range}" val, restart = find_matches(first_range, next_range) return if val == nil puts "Value is #{val.inspect}." if val + val == val * val puts "Isn't that special?" else restart.call end end def find_matches(first_range, next_range) callcc do | out | for i in first_range for j in next_range return_resumably(i, out) if i == j end end nil end end def return_resumably(primary_retval, return_continuation) callcc do | resume_continuation | return_continuation.call(primary_retval, resume_continuation) end end if __FILE__ == $0 find_special_number(0..3, 1..5) find_special_number(3..8, 4..7) end % ruby continuation-loop.rb == Look for a special value in 0..3 and 1..5 Value is 1. Value is 2. Isn't that special? == Look for a special value in 3..8 and 4..7 Value is 4. Value is 5. Value is 6. Value is 7. ======== But that forces the programmer calling find_matches know obscure things. I'd still like to find a way to suspend an arbitrary computation, get a "resumer" that can be passed around and called anywhere to return the next value. Maybe time to try to find those Scheme documents from the mid-80's. -- Brian Marick, marick@testing.com www.testing.com - Software testing services and resources www.testingcraft.com - Where software testers exchange techniques www.visibleworkings.com - Adequate understanding of system internals