module Control Break = Class.new Next = Class.new Redo = Class.new @stack = [] def self.unique_name :"_#{@stack.size}" end def self.push_scope @stack.push self.unique_name @stack.last end def self.pop_scope @stack.pop end def self.last @stack.last end def self.break(label = @stack.last) throw label, Control::Break end def self.next(label = @stack.last) throw label, Control::Next end def self.redo(label = @stack.last) throw label, Control::Redo end def self.label self.last end end module Enumerable def with_control return to_enum(__method__) unless block_given? name = Control.push_scope each{|*a| ret = catch(name){ yield(*a) } break if ret == Control::Break next if ret == Control::Next redo if ret == Control::Redo ret } ensure Control.pop_scope end end 1.upto(10).with_control{|i| a = Control.label 1.upto(10).with_control{|j| Control.break a if i > 3 && j > 3 p [i, j] } }
Standard input is empty
1 3 5 7 9 [1, 1] [1, 2] [1, 3] [1, 4] [1, 5] [1, 6] [1, 7] [1, 8] [1, 9] [1, 10] [2, 1] [2, 2] [2, 3] [2, 4] [2, 5] [2, 6] [2, 7] [2, 8] [2, 9] [2, 10] [3, 1] [3, 2] [3, 3] [3, 4] [3, 5] [3, 6] [3, 7] [3, 8] [3, 9] [3, 10] [4, 1] [4, 2] [4, 3]