Class | Generator
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

new(enum = nil, &block)

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

current()

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

each() {|self.next| ...}

Rewinds the generator and enumerates the elements.

[Source]

    # File generator.rb, line 157
      def each
        rewind

        until end?
          yield self.next
        end

        self
      end

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

index()

Returns the current index (position) counting from zero.

[Source]

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

next()

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

next?()

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

[Source]

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

pos()

Returns the current index (position) counting from zero.

[Source]

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

rewind()

Rewinds the generator.

[Source]

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

        self
      end

yield(value)

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]