In Files

  • generator.rb

Parent

Included Modules

Class/Module Index [+]

Quicksearch

Generator

Generator converts an internal iterator (i.e. an Enumerable object) to an external iterator.

Note that it is not very fast since it is implemented using continuations, which are currently slow.

Example

require 'generator'

# Generator from an Enumerable object
g = Generator.new(['A', 'B', 'C', 'Z'])

while g.next?
  puts g.next
end

# Generator from a block
g = Generator.new { |g|
  for i in 'A'..'C'
    g.yield i
  end

  g.yield 'Z'
}

# The same result as above
while g.next?
  puts g.next
end

Public Class Methods

new(enum = nil, &block) click to toggle source

Creates a new generator either from an Enumerable object or from a block.

In the former, block is ignored even if given.

In the latter, the given block is called with the generator itself, and expected to call the yield method for each element.

 
               # File generator.rb, line 69
def initialize(enum = nil, &block)
  if enum
    @block = proc { |g|
      enum.each { |x| g.yield x }
    }
  else
    @block = block
  end

  @index = 0
  @queue = []
  @cont_next = @cont_yield = @cont_endp = nil

  if @cont_next = callcc { |c| c }
    @block.call(self)

    @cont_endp.call(nil) if @cont_endp
  end

  self
end
            

Public Instance Methods

current() click to toggle source

Returns the element at the current position.

 
               # File generator.rb, line 141
def current()
  if @queue.empty?
    raise EOFError, "no more elements available"
  end

  @queue.first
end
            
each() click to toggle source

Rewinds the generator and enumerates the elements.

 
               # File generator.rb, line 157
def each
  rewind

  until end?
    yield self.next
  end

  self
end
            
end?() click to toggle source

Returns true if the generator has reached the end.

 
               # File generator.rb, line 102
def end?()
  if @cont_endp = callcc { |c| c }
    @cont_yield.nil? && @queue.empty?
  else
    @queue.empty?
  end
end
            
index() click to toggle source

Returns the current index (position) counting from zero.

 
               # File generator.rb, line 116
def index()
  @index
end
            
next() click to toggle source

Returns the element at the current position and moves forward.

 
               # File generator.rb, line 126
def next()
  if end?
    raise EOFError, "no more elements available"
  end

  if @cont_next = callcc { |c| c }
    @cont_yield.call(nil) if @cont_yield
  end

  @index += 1

  @queue.shift
end
            
next?() click to toggle source

Returns true if the generator has not reached the end yet.

 
               # File generator.rb, line 111
def next?()
  !end?
end
            
pos() click to toggle source

Returns the current index (position) counting from zero.

 
               # File generator.rb, line 121
def pos()
  @index
end
            
rewind() click to toggle source

Rewinds the generator.

 
               # File generator.rb, line 150
def rewind()
  initialize(nil, &@block) if @index.nonzero?

  self
end
            
yield(value) click to toggle source

Yields an element to the generator.

 
               # File generator.rb, line 92
def yield(value)
  if @cont_yield = callcc { |c| c }
    @queue << value
    @cont_next.call(nil)
  end

  self
end