1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* enumerator.c: Improve documentation. Patch by Dave Copeland.

[Ruby 1.9 - Bug #4757]


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@31704 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
drbrain 2011-05-22 23:33:21 +00:00
parent b7576c3d7a
commit 6cfb4b614a
2 changed files with 197 additions and 142 deletions

View file

@ -1,3 +1,8 @@
Mon May 23 08:32:59 2011 Eric Hodel <drbrain@segment7.net>
* enumerator.c: Improve documentation. Patch by Dave Copeland.
[Ruby 1.9 - Bug #4757]
Mon May 23 07:19:45 2011 Martin Bosslet <Martin.Bosslet@googlemail.com>
* NEWS (openssl): Infinite length support. Different behavior of

View file

@ -17,33 +17,52 @@
/*
* Document-class: Enumerator
*
* A class which provides a method `each' to be used as an Enumerable
* object.
* A class which allows both internal and external iteration.
*
* An enumerator can be created by following methods.
* An Enumerator can be created by the following methods.
* - Kernel#to_enum
* - Kernel#enum_for
* - Enumerator.new
*
* Also, most iteration methods without a block returns an enumerator.
* For example, Array#map returns an enumerator if a block is not given.
* The enumerator has the with_index method.
* So ary.map.with_index works as follows.
* Most methods have two forms: a block form where the contents
* are evaluated for each item in the enumeration, and a non-block form
* which returns a new Enumerator wrapping the iteration.
*
* p %w[foo bar baz].map.with_index {|w,i| "#{i}:#{w}" }
* #=> ["0:foo", "1:bar", "2:baz"]
* enumerator = %w(one two three).each
* puts enumerator.class # => Enumerator
* enumerator.each_with_object("foo") do |item,obj|
* puts "#{obj}: #{item}"
* end
* # foo: one
* # foo: two
* # foo: three
* enum_with_obj = enumerator.each_with_object("foo")
* puts enum_with_obj.class # => Enumerator
* enum_with_obj.each do |item,obj|
* puts "#{obj: #{item}"
* end
* # foo: one
* # foo: two
* # foo: three
*
* An enumerator object can be used as an external iterator.
* I.e. Enumerator#next returns the next value of the iterator.
* Enumerator#next raises StopIteration at end.
* This allows you to chain Enumerators together. For example, you
* can map a list's elements to strings containing the index
* and the element as a string via:
*
* puts %w[foo bar baz].map.with_index {|w,i| "#{i}:#{w}" }
* # => ["0:foo", "1:bar", "2:baz"]
*
* An Enumerator can also be used as an external iterator.
* For example, Enumerator#next returns the next value of the iterator
* or raises StopIteration if the Enumerator is at the end.
*
* e = [1,2,3].each # returns an enumerator object.
* p e.next #=> 1
* p e.next #=> 2
* p e.next #=> 3
* p e.next #raises StopIteration
* puts e.next # => 1
* puts e.next # => 2
* puts e.next # => 3
* puts e.next # raises StopIteration
*
* An external iterator can be used to implement an internal iterator as follows.
* You can use this to implement an internal iterator as follows:
*
* def ext_each(e)
* while true
@ -58,21 +77,22 @@
* end
*
* o = Object.new
*
* def o.each
* p yield
* p yield(1)
* p yield(1, 2)
* puts yield
* puts yield(1)
* puts yield(1, 2)
* 3
* end
*
* # use o.each as an internal iterator directly.
* p o.each {|*x| p x; [:b, *x] }
* #=> [], [:b], [1], [:b, 1], [1, 2], [:b, 1, 2], 3
* puts o.each {|*x| puts x; [:b, *x] }
* # => [], [:b], [1], [:b, 1], [1, 2], [:b, 1, 2], 3
*
* # convert o.each to an external iterator for
* # implementing an internal iterator.
* p ext_each(o.to_enum) {|*x| p x; [:b, *x] }
* #=> [], [:b], [1], [:b, 1], [1, 2], [:b, 1, 2], 3
* puts ext_each(o.to_enum) {|*x| puts x; [:b, *x] }
* # => [], [:b], [1], [:b, 1], [1, 2], [:b, 1, 2], 3
*
*/
VALUE rb_cEnumerator;
@ -151,22 +171,31 @@ enumerator_ptr(VALUE obj)
}
/*
* call-seq:
* obj.to_enum(method = :each, *args)
* obj.enum_for(method = :each, *args)
* call-seq:
* obj.to_enum(method = :each, *args)
* obj.enum_for(method = :each, *args)
*
* Returns Enumerator.new(self, method, *args).
* Creates a new Enumerator which will enumerate by on calling +method+ on
* +obj+.
*
* e.g.:
* +method+:: the method to call on +obj+ to generate the enumeration
* +args+:: arguments that will be passed in +method+ <i>in addition</i>
* to the item itself. Note that the number of args
* must not exceed the number expected by +method+
*
* str = "xyz"
* === Example
*
* enum = str.enum_for(:each_byte)
* a = enum.map {|b| '%02x' % b } #=> ["78", "79", "7a"]
* str = "xyz"
*
* # protects an array from being modified
* a = [1, 2, 3]
* some_method(a.to_enum)
* enum = str.enum_for(:each_byte)
* enum.each { |b| puts b }
* # => 120
* # => 121
* # => 122
*
* # protect an array from being modified by some_method
* a = [1, 2, 3]
* some_method(a.to_enum)
*
*/
static VALUE
@ -217,36 +246,38 @@ enumerator_init(VALUE enum_obj, VALUE obj, VALUE meth, int argc, VALUE *argv)
}
/*
* call-seq:
* Enumerator.new(obj, method = :each, *args)
* Enumerator.new { |y| ... }
* call-seq:
* Enumerator.new { |yielder| ... }
* Enumerator.new(obj, method = :each, *args)
*
* Creates a new Enumerator object, which is to be used as an
* Enumerable object iterating in a given way.
* Creates a new Enumerator object, which can be used as an
* Enumerable.
*
* In the first form, a generated Enumerator iterates over the given
* object using the given method with the given arguments passed.
* Use of this form is discouraged. Use Kernel#enum_for(), alias
* to_enum, instead.
* In the first form, iteration is defined by the given block, in
* which a "yielder" object, given as block parameter, can be used to
* yield a value by calling the +yield+ method (aliased as +<<+):
*
* e = Enumerator.new(ObjectSpace, :each_object)
* #-> ObjectSpace.enum_for(:each_object)
* fib = Enumerator.new do |y|
* a = b = 1
* loop do
* y << a
* a, b = b, a + b
* end
* end
*
* e.select { |obj| obj.is_a?(Class) } #=> array of all classes
* p fib.take(10) # => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
*
* In the second form, iteration is defined by the given block, in
* which a "yielder" object given as block parameter can be used to
* yield a value by calling the +yield+ method, alias +<<+.
* In the second, deprecated, form, a generated Enumerator iterates over the
* given object using the given method with the given arguments passed.
*
* fib = Enumerator.new { |y|
* a = b = 1
* loop {
* y << a
* a, b = b, a + b
* }
* }
* Use of this form is discouraged. Use Kernel#enum_for or Kernel#to_enum
* instead.
*
* e = Enumerator.new(ObjectSpace, :each_object)
* #-> ObjectSpace.enum_for(:each_object)
*
* e.select { |obj| obj.is_a?(Class) } #=> array of all classes
*
* p fib.take(10) #=> [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
*/
static VALUE
enumerator_initialize(int argc, VALUE *argv, VALUE obj)
@ -320,11 +351,11 @@ enumerator_block_call(VALUE obj, rb_block_call_func *func, VALUE arg)
}
/*
* call-seq:
* enum.each {...}
* call-seq:
* enum.each {...}
*
* Iterates the given block using the object and the method specified
* in the first place. If no block is given, returns self.
* Iterates over the block according to how this Enumerable was constructed.
* If no block is given, returns self.
*
*/
static VALUE
@ -350,12 +381,15 @@ enumerator_with_index_i(VALUE val, VALUE m, int argc, VALUE *argv)
}
/*
* call-seq:
* e.with_index(offset = 0) {|(*args), idx| ... }
* e.with_index(offset = 0)
* call-seq:
* e.with_index(offset = 0) {|(*args), idx| ... }
* e.with_index(offset = 0)
*
* Iterates the given block for each element with an index, which
* starts from +offset+. If no block is given, returns an enumerator.
* Iterates the given block for each element with an index, which
* starts from +offset+. If no block is given, returns a new Enumerator
* that includes the index, starting from +offset+
*
* +offset+:: the starting index to use
*
*/
static VALUE
@ -370,12 +404,13 @@ enumerator_with_index(int argc, VALUE *argv, VALUE obj)
}
/*
* call-seq:
* e.each_with_index {|(*args), idx| ... }
* e.each_with_index
* call-seq:
* e.each_with_index {|(*args), idx| ... }
* e.each_with_index
*
* Same as Enumerator#with_index, except each_with_index does not
* receive an offset argument.
* Same as Enumerator#with_index(0), i.e. there is no starting offset.
*
* If no block is given, a new Enumerator is returned that includes the index.
*
*/
static VALUE
@ -394,15 +429,31 @@ enumerator_with_object_i(VALUE val, VALUE memo, int argc, VALUE *argv)
}
/*
* call-seq:
* e.with_object(obj) {|(*args), memo_obj| ... }
* e.with_object(obj)
* call-seq:
* e.with_object(obj) {|(*args), obj| ... }
* e.with_object(obj)
*
* Iterates the given block for each element with an arbitrary
* object given, and returns the initially given object.
* Iterates the given block for each element with an arbitrary object, +obj+,
* and returns +obj+
*
* If no block is given, returns an enumerator.
* If no block is given, returns a new Enumerator.
*
* === Example
*
* to_three = Enumerator.new do |y|
* 3.times do |x|
* y << x
* end
* end
*
* to_three_with_string = to_three.with_object("foo")
* to_three_with_string.each do |x,string|
* puts "#{string}: #{x}"
* end
*
* # => foo:0
* # => foo:1
* # => foo:2
*/
static VALUE
enumerator_with_object(VALUE obj, VALUE memo)
@ -478,11 +529,14 @@ get_next_values(VALUE obj, struct enumerator *e)
* call-seq:
* e.next_values -> array
*
* Returns the next object as an array in the enumerator,
* and move the internal position forward.
* When the position reached at the end, StopIteration is raised.
* Returns the next object as an array in the enumerator, and move the
* internal position forward. When the position reached at the end,
* StopIteration is raised.
*
* This method can be used to distinguish <code>yield</code> and <code>yield nil</code>.
* This method can be used to distinguish <code>yield</code> and <code>yield
* nil</code>.
*
* === Example
*
* o = Object.new
* def o.each
@ -512,9 +566,9 @@ get_next_values(VALUE obj, struct enumerator *e)
* # yield nil [nil] nil
* # yield [1, 2] [[1, 2]] [1, 2]
*
* Note that enumeration sequence by next_values method does not affect other
* non-external enumeration methods, unless underlying iteration
* methods itself has side-effect, e.g. IO#each_line.
* Note that enumeration sequenced by +next_values+ does not affect other
* non-external enumeration methods, unless underlying iteration methods
* itself has side-effect, e.g. IO#each_line.
*
*/
@ -557,9 +611,10 @@ ary2sv(VALUE args, int dup)
* call-seq:
* e.next -> object
*
* Returns the next object in the enumerator, and move the internal
* position forward. When the position reached at the end, StopIteration
* is raised.
* Returns the next object in the enumerator, and move the internal position
* forward. When the position reached at the end, StopIteration is raised.
*
* === Example
*
* a = [1,2,3]
* e = a.to_enum
@ -568,9 +623,9 @@ ary2sv(VALUE args, int dup)
* p e.next #=> 3
* p e.next #raises StopIteration
*
* Note that enumeration sequence by next method does not affect other
* non-external enumeration methods, unless underlying iteration
* methods itself has side-effect, e.g. IO#each_line.
* Note that enumeration sequence by +next+ does not affect other non-external
* enumeration methods, unless the underlying iteration methods itself has
* side-effect, e.g. IO#each_line.
*
*/
@ -596,9 +651,11 @@ enumerator_peek_values(VALUE obj)
* call-seq:
* e.peek_values -> array
*
* Returns the next object as an array in the enumerator,
* but don't move the internal position forward.
* When the position reached at the end, StopIteration is raised.
* Returns the next object as an array, similar to Enumerator#next_values, but
* doesn't move the internal position forward. If the position is already at
* the end, StopIteration is raised.
*
* === Example
*
* o = Object.new
* def o.each
@ -628,10 +685,12 @@ enumerator_peek_values_m(VALUE obj)
* call-seq:
* e.peek -> object
*
* Returns the next object in the enumerator, but don't move the internal
* position forward. When the position reached at the end, StopIteration
* Returns the next object in the enumerator, but doesn't move the internal
* position forward. If the position is already at the end, StopIteration
* is raised.
*
* === Example
*
* a = [1,2,3]
* e = a.to_enum
* p e.next #=> 1
@ -655,38 +714,26 @@ enumerator_peek(VALUE obj)
* call-seq:
* e.feed obj -> nil
*
* Set the value for the next yield in the enumerator returns.
* Set the value to be returned by the next call to +yield+ by the enumerator.
* If the value is not set, the +yield+ returns +nil+ and the value is cleared
* after it is used the first time.
*
* If the value is not set, the yield returns nil.
* +obj+:: the object to return from the next call to the Enumerator's +yield+
*
* This value is cleared after used.
* === Example
*
* o = Object.new
* def o.each
* # (2)
* x = yield
* p x #=> "foo"
* # (5)
* x = yield
* p x #=> nil
* # (7)
* x = yield
* # not reached
* p x
* three_times = Enumerator.new do |yielder|
* 3.times do |x|
* result = yielder.yield(x)
* puts result
* end
* end
* e = o.to_enum
* # (1)
* e.next
* # (3)
* e.feed "foo"
* # (4)
* e.next
* # (6)
* e.next
* # (8)
*
* three_times.next # => 0
* three_times.feed("foo")
* three_times.next # => 1, prints "foo"
* three_times.next # => 2, prints nothing
*/
static VALUE
enumerator_feed(VALUE obj, VALUE v)
{
@ -704,7 +751,7 @@ enumerator_feed(VALUE obj, VALUE v)
* call-seq:
* e.rewind -> e
*
* Rewinds the enumeration sequence by the next method.
* Rewinds the enumeration sequence by one step.
*
* If the enclosed object responds to a "rewind" method, it is called.
*/
@ -785,7 +832,7 @@ inspect_enumerator(VALUE obj, VALUE dummy, int recur)
* call-seq:
* e.inspect -> string
*
* Create a printable version of <i>e</i>.
* Creates a printable version of <i>e</i>.
*/
static VALUE
@ -1027,27 +1074,27 @@ generator_each(VALUE obj)
}
/*
* Document-class: StopIteration
* Document-class: StopIteration
*
* Raised to stop the iteration, in particular by Enumerator#next. It is
* rescued by Kernel#loop.
* Raised to stop the iteration, in particular by Enumerator#next. It is
* rescued by Kernel#loop.
*
* loop do
* puts "Hello"
* raise StopIteration
* puts "World"
* end
* puts "Done!"
* loop do
* puts "Hello"
* raise StopIteration
* puts "World"
* end
* puts "Done!"
*
* <em>produces:</em>
* <em>produces:</em>
*
* Hello
* Done!
* Hello
* Done!
*/
/*
* call-seq:
* stopiteration.result -> value
* result -> value
*
* Returns the return value of the iterator.
*
@ -1058,14 +1105,17 @@ generator_each(VALUE obj)
* yield 3
* 100
* end
*
* e = o.to_enum
* p e.next #=> 1
* p e.next #=> 2
* p e.next #=> 3
*
* puts e.next #=> 1
* puts e.next #=> 2
* puts e.next #=> 3
*
* begin
* e.next
* rescue StopIteration
* p $!.result #=> 100
* rescue StopIteration => ex
* puts ex.result #=> 100
* end
*
*/