* lib/generator.rb: Add rdoc documentation.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4797 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
knu 2003-10-17 14:01:26 +00:00
parent a4ba07c242
commit a7ddb2e342
2 changed files with 84 additions and 4 deletions

View File

@ -1,3 +1,7 @@
Fri Oct 17 23:00:30 2003 Akinori MUSHA <knu@iDaemons.org>
* lib/generator.rb: Add rdoc documentation.
Fri Oct 17 22:16:42 2003 Akinori MUSHA <knu@iDaemons.org> Fri Oct 17 22:16:42 2003 Akinori MUSHA <knu@iDaemons.org>
* lib/set.rb: Reword and fix Overview. * lib/set.rb: Reword and fix Overview.

View File

@ -1,5 +1,7 @@
#!/usr/bin/env ruby #!/usr/bin/env ruby
# #
# generator.rb - converts an internal iterator to an external iterator
#++
# Copyright (c) 2001,2003 Akinori MUSHA <knu@iDaemons.org> # Copyright (c) 2001,2003 Akinori MUSHA <knu@iDaemons.org>
# #
# All rights reserved. You can redistribute and/or modify it under # All rights reserved. You can redistribute and/or modify it under
@ -8,14 +10,60 @@
# $Idaemons: /home/cvs/rb/generator.rb,v 1.8 2001/10/03 08:54:32 knu Exp $ # $Idaemons: /home/cvs/rb/generator.rb,v 1.8 2001/10/03 08:54:32 knu Exp $
# $RoughId: generator.rb,v 1.10 2003/10/14 19:36:58 knu Exp $ # $RoughId: generator.rb,v 1.10 2003/10/14 19:36:58 knu Exp $
# $Id$ # $Id$
#
# == Overview
#
# This library provides the Generator class, which converts an
# internal iterator (i.e. an Enumerable object) to an external
# iterator. In that form, you can roll many iterators independently.
#
# The SyncEnumerator class, which is implemented using Generator,
# makes it easy to roll many Enumerable objects synchronously.
#
# See the respective classes for examples of usage.
# #
# class Generator - converts an internal iterator to an external iterator # 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
# continuation, which currently is 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
#
class Generator class Generator
include Enumerable include Enumerable
# 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.
def initialize(enum = nil, &block) def initialize(enum = nil, &block)
if enum if enum
@block = proc { |g| @block = proc { |g|
@ -38,6 +86,7 @@ class Generator
self self
end end
# Yields an element to the generator.
def yield(value) def yield(value)
if @cont_yield = callcc { |c| c } if @cont_yield = callcc { |c| c }
@queue << value @queue << value
@ -47,6 +96,7 @@ class Generator
self self
end end
# Returns true if the generator has reached the end.
def end?() def end?()
if @cont_endp = callcc { |c| c } if @cont_endp = callcc { |c| c }
@cont_yield.nil? && @queue.empty? @cont_yield.nil? && @queue.empty?
@ -55,18 +105,22 @@ class Generator
end end
end end
# Returns true if the generator has not reached the end yet.
def next?() def next?()
!end? !end?
end end
# Returns the current index (position) counting from zero.
def index() def index()
@index @index
end end
# Returns the current index (position) counting from zero.
def pos() def pos()
@index @index
end end
# Returns the element at the current position and moves forward.
def next() def next()
if end? if end?
raise EOFError, "no more element is supplied" raise EOFError, "no more element is supplied"
@ -81,6 +135,7 @@ class Generator
@queue.shift @queue.shift
end end
# Returns the element at the current position.
def current() def current()
if @queue.empty? if @queue.empty?
raise EOFError, "no more element is supplied" raise EOFError, "no more element is supplied"
@ -89,12 +144,14 @@ class Generator
@queue.first @queue.first
end end
# Rewinds the generator.
def rewind() def rewind()
initialize(nil, &@block) if @index.nonzero? initialize(nil, &@block) if @index.nonzero?
self self
end end
# Rewinds the generator and enumerates the elements.
def each def each
rewind rewind
@ -107,24 +164,42 @@ class Generator
end end
# #
# class SyncEnumerator - enumerates multiple internal iterators synchronously # SyncEnumerator creates an Enumerable object from multiple Enumerable
# objects and enumerates them synchronously.
#
# == Example
#
# require 'generator'
#
# s = SyncEnumerator.new([1,2,3], ['a', 'b', 'c'])
#
# # Yields [1, 'a'], [2, 'b'], and [3,'c']
# s.each { |row| puts row.join(', ') }
# #
class SyncEnumerator class SyncEnumerator
include Enumerable include Enumerable
# Creates a new SyncEnumerator which enumerates rows of given
# Enumerable objects.
def initialize(*enums) def initialize(*enums)
@gens = enums.map { |e| Generator.new(e) } @gens = enums.map { |e| Generator.new(e) }
end end
# Returns the number of enumerated Enumerable objects, i.e. the size
# of each row.
def size def size
@gens.size @gens.size
end end
# Returns the number of enumerated Enumerable objects, i.e. the size
# of each row.
def length def length
@gens.length @gens.length
end end
# Returns true if the given nth Enumerable object has reached the
# end. If no argument is given, returns true if any of the
# Enumerable objects has reached the end.
def end?(i = nil) def end?(i = nil)
if i.nil? if i.nil?
@gens.detect { |g| g.end? } ? true : false @gens.detect { |g| g.end? } ? true : false
@ -133,6 +208,7 @@ class SyncEnumerator
end end
end end
# Enumerates rows of the Enumerable objects.
def each def each
@gens.each { |g| g.rewind } @gens.each { |g| g.rewind }