From: Joel VanderWerf Date: 2007-02-11T05:23:38+09:00 Subject: Re: Jumping to "the next one" in something#each Garance A Drosehn wrote: > ARGV.each { |arg| > case arg > when "-f" > ...do something with the *next* value of |arg|... > end > } The following works with any Enumerable, doesn't use threads, continuations, or generators, doesn't construct temp arrays (except to hold the next value(s)) or do any shifting on the original argument, and has fairly nice syntax (but you have to remember not to fall off the end of your block with an integer value). It handles corner cases AFAICT. Any suggestions for a better name than #each2? module Enumerable class InsufficientDataError < StandardError; end def each2 req = first = rest = nil each do |x| if req req -= 1 rest << x next if req > 0 req = yield first, rest first = nil rest = nil else req = yield x, nil end if req if req.kind_of?(Integer) and req > 0 first = x rest = [] else raise ArgumentError, "Bad request: next #{req.inspect}" end end end if req and req > 0 raise InsufficientDataError, "Ran out of data fulfilling request: next #{req}" end end end (1..10).each2 do |x, rest| next 2 if (x == 3 or x == 7) and not rest puts "x = #{x}, rest = #{rest.inspect}" nil ## make sure not to request more entries by returning an integer end %w{ -f foo -b bar --copy src dst }.each2 do |arg, values| case arg when "-f", "-b" next 1 unless values puts "#{arg} #{values[0]}" when "--copy" next 2 unless values puts "#{arg} #{values.join(" ")}" end nil ## make sure not to request more entries by returning an integer end __END__ Output: x = 1, rest = nil x = 2, rest = nil x = 3, rest = [4, 5] x = 6, rest = nil x = 7, rest = [8, 9] x = 10, rest = nil -f foo -b bar --copy src dst -- vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407