fork download
  1. module Control
  2. Break = Class.new
  3. Next = Class.new
  4. Redo = Class.new
  5. @stack = []
  6. def self.unique_name
  7. :"_#{@stack.size}"
  8. end
  9. def self.push_scope
  10. @stack.push self.unique_name
  11. @stack.last
  12. end
  13. def self.pop_scope
  14. @stack.pop
  15. end
  16. def self.last
  17. @stack.last
  18. end
  19. def self.break(label = @stack.last)
  20. throw label, Control::Break
  21. end
  22. def self.next(label = @stack.last)
  23. throw label, Control::Next
  24. end
  25. def self.redo(label = @stack.last)
  26. throw label, Control::Redo
  27. end
  28. def self.label
  29. self.last
  30. end
  31. end
  32.  
  33. module Enumerable
  34. def with_control
  35. return to_enum(__method__) unless block_given?
  36. name = Control.push_scope
  37. each{|*a|
  38. ret = catch(name){ yield(*a) }
  39. break if ret == Control::Break
  40. next if ret == Control::Next
  41. redo if ret == Control::Redo
  42. ret
  43. }
  44. ensure
  45. Control.pop_scope
  46. end
  47. end
  48.  
  49.  
  50. 1.upto(10).with_control{|i|
  51. a = Control.label
  52. 1.upto(10).with_control{|j|
  53. Control.break a if i > 3 && j > 3
  54. p [i, j]
  55. }
  56. }
  57.  
  58.  
Success #stdin #stdout 0.02s 7444KB
stdin
Standard input is empty
stdout
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]