[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Re: Jumping to "the next one" in something#each

Joel VanderWerf

2/10/2007 8:24:00 PM

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