mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Document and test Enumerator.produce
Co-authored-by: Victor Shepelev <zverok.offline@gmail.com>
This commit is contained in:
parent
775037613b
commit
ac3e8834e0
2 changed files with 67 additions and 0 deletions
22
enumerator.c
22
enumerator.c
|
@ -2890,6 +2890,28 @@ producer_size(VALUE obj, VALUE args, VALUE eobj)
|
|||
return DBL2NUM(HUGE_VAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* Enumerator.produce(initial = nil) { |val| } -> enumerator
|
||||
*
|
||||
* Creates an infinite enumerator from any block, just called over and
|
||||
* over. Result of the previous iteration is passed to the next one.
|
||||
* If +initial+ is provided, it is passed to the first iteration, and
|
||||
* becomes the first element of the enumerator; if it is not provided,
|
||||
* first iteration receives +nil+, and its result becomes first
|
||||
* element of the iterator.
|
||||
*
|
||||
* Raising StopIteration from the block stops an iteration.
|
||||
*
|
||||
* Examples of usage:
|
||||
*
|
||||
* Enumerator.produce(1, &:succ) # => enumerator of 1, 2, 3, 4, ....
|
||||
*
|
||||
* Enumerator.produce { rand(10) } # => infinite random number sequence
|
||||
*
|
||||
* ancestors = Enumerator.produce(node) { |prev| node = prev.parent or raise StopIteration }
|
||||
* enclosing_section = ancestors.find { |n| n.type == :section }
|
||||
*/
|
||||
static VALUE
|
||||
enumerator_s_produce(int argc, VALUE *argv, VALUE klass)
|
||||
{
|
||||
|
|
|
@ -811,4 +811,49 @@ class TestEnumerator < Test::Unit::TestCase
|
|||
e5.inspect
|
||||
)
|
||||
end
|
||||
|
||||
def test_produce
|
||||
assert_raise(ArgumentError) { Enumerator.produce }
|
||||
|
||||
# Without initial object
|
||||
passed_args = []
|
||||
enum = Enumerator.produce { |obj| passed_args << obj; (obj || 0).succ }
|
||||
assert_instance_of(Enumerator, enum)
|
||||
assert_equal Float::INFINITY, enum.size
|
||||
assert_equal [1, 2, 3], enum.take(3)
|
||||
assert_equal [nil, 1, 2], passed_args
|
||||
|
||||
# With initial object
|
||||
passed_args = []
|
||||
enum = Enumerator.produce(1) { |obj| passed_args << obj; obj.succ }
|
||||
assert_instance_of(Enumerator, enum)
|
||||
assert_equal Float::INFINITY, enum.size
|
||||
assert_equal [1, 2, 3], enum.take(3)
|
||||
assert_equal [1, 2], passed_args
|
||||
|
||||
# Raising StopIteration
|
||||
words = "The quick brown fox jumps over the lazy dog.".scan(/\w+/)
|
||||
enum = Enumerator.produce { words.shift or raise StopIteration }
|
||||
assert_equal Float::INFINITY, enum.size
|
||||
assert_instance_of(Enumerator, enum)
|
||||
assert_equal %w[The quick brown fox jumps over the lazy dog], enum.to_a
|
||||
|
||||
# Raising StopIteration
|
||||
object = [[[["abc", "def"], "ghi", "jkl"], "mno", "pqr"], "stuv", "wxyz"]
|
||||
enum = Enumerator.produce(object) { |obj|
|
||||
obj.respond_to?(:first) or raise StopIteration
|
||||
obj.first
|
||||
}
|
||||
assert_equal Float::INFINITY, enum.size
|
||||
assert_instance_of(Enumerator, enum)
|
||||
assert_nothing_raised {
|
||||
assert_equal [
|
||||
[[[["abc", "def"], "ghi", "jkl"], "mno", "pqr"], "stuv", "wxyz"],
|
||||
[[["abc", "def"], "ghi", "jkl"], "mno", "pqr"],
|
||||
[["abc", "def"], "ghi", "jkl"],
|
||||
["abc", "def"],
|
||||
"abc",
|
||||
], enum.to_a
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Add table
Reference in a new issue