Generator (Class)

In: generator.rb
Parent: Object

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

Methods

current   each   end?   index   new   next   next?   pos   rewind   yield  

Included Modules

Enumerable

Public Class methods

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.

[Source]

# 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

Returns the element at the current position.

[Source]

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

    @queue.first
  end

Rewinds the generator and enumerates the elements.

[Source]

# File generator.rb, line 157
  def each
    rewind

    until end?
      yield self.next
    end

    self
  end

Returns true if the generator has reached the end.

[Source]

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

Returns the current index (position) counting from zero.

[Source]

# File generator.rb, line 116
  def index()
    @index
  end

Returns the element at the current position and moves forward.

[Source]

# 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

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

[Source]

# File generator.rb, line 111
  def next?()
    !end?
  end

Returns the current index (position) counting from zero.

[Source]

# File generator.rb, line 121
  def pos()
    @index
  end

Rewinds the generator.

[Source]

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

    self
  end

Yields an element to the generator.

[Source]

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

    self
  end

[Validate]