Ruby 1.9 has, for a while now, supported Enumerators. These are Enumerable objects returned by iterator methods when the methods are invoked with no blocks. Until recently, Enumerators were still internal, Ruby-style iterators that you invoke with each.
But that has changed. I haven't seen this discussed anywhere in English, but recent builds of Ruby 1.9 (my build is from August 17th) also define methods next and next? on Enumerator. These are Python-style (and Java-style) external iterators:
Update: 8/24/07: Matz has just removed the next? method. So you now have to be ready to catch StopIteration when using Enumerators. This means that the twine method below doesn't work anymore..
r = 1..3 # An enumerable object e = r.each # An enumerator object e.next # => 1 e.next # => 2 e.next # => 3 e.next # StopIteration exception raised
True external iterators make the age-old problem of parallel iteration in Ruby trivial to solve. Here are some examples:
def twine(*enumerables)
enumerators = enumerables.map { |x| x.each }
while not enumerators.empty?
e = enumerators.shift
if e.next?
yield e.next
enumerators << e
end
end
end
def braid(*enumerables)
enumerators = enumerables.map { |x| x.each }
begin
loop do
values = enumerators.map {|x| x.next }
yield *values
end
rescue StopIteration
# This is normal termination condition
end
end
a = [1,2,3]
b = [4,5,6]
twine(a,b,'a'..'b') { |x| puts x }
braid(a,b,7..10) { |x,y,z| print "#{x},#{y},#{z}\n" }
It appears that these new external iterators are not build on the old Generator library which used continuations (I think). Instead, they use a new Fiber class (a kind of micro-thread). It is not documented yet, but its in there in recent 1.9 builds. If you know how to use Fiber, feel free to explain in the comments.




hi david,
fiber : this reminds me of Win32 fiber's (http://msdn2.microsoft.com/en-us/library/ms682661.aspx)
Win32 implements fibers in the user space . They don't have a kernel stack(datastructure) of their own.
BR,
~A
The following functions are used with fibers.
Function Description
ConvertFiberToThread Converts the current fiber into a thread.
ConvertThreadToFiber Converts the current thread into a fiber.
ConvertThreadToFiberEx Converts the current thread into a fiber.
CreateFiber Allocates a fiber object, assigns it a stack, and sets up execution "to" begin at the specified start address.
CreateFiberEx Allocates a fiber object, assigns it a stack, and sets up execution "to" begin at the specified start address.
DeleteFiber Deletes an existing fiber.
FiberProc An application-defined function used with the CreateFiber function.
FlsAlloc Allocates a fiber local storage (FLS) index.
FlsFree Releases an FLS index.
FlsGetValue Retrieves the value in the calling fiber's FLS slot for a specified FLS index.
FlsSetValue Stores a value in the calling fiber's FLS slot for a specified FLS index.
IsThreadAFiber Determines whether the current thread is a fiber.
SwitchToFiber Schedules a fiber.