1
0
Fork 0
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:
Akinori MUSHA 2019-09-12 20:15:03 +09:00
parent 775037613b
commit ac3e8834e0
No known key found for this signature in database
GPG key ID: C5D7717121727E34
2 changed files with 67 additions and 0 deletions

View file

@ -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)
{

View file

@ -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