[前][次][番号順一覧][スレッド一覧]

ruby-changes:57726

From: Akinori <ko1@a...>
Date: Thu, 12 Sep 2019 20:19:38 +0900 (JST)
Subject: [ruby-changes:57726] ac3e8834e0 (master): Document and test Enumerator.produce

https://git.ruby-lang.org/ruby.git/commit/?id=ac3e8834e0

From ac3e8834e030f62d2d313ec60cd7ed3c14c9ea5e Mon Sep 17 00:00:00 2001
From: Akinori MUSHA <knu@i...>
Date: Thu, 12 Sep 2019 20:15:03 +0900
Subject: Document and test Enumerator.produce

Co-authored-by: Victor Shepelev <zverok.offline@g...>

diff --git a/enumerator.c b/enumerator.c
index fcf49b3..43008bc 100644
--- a/enumerator.c
+++ b/enumerator.c
@@ -2890,6 +2890,28 @@ producer_size(VALUE obj, VALUE args, VALUE eobj) https://github.com/ruby/ruby/blob/trunk/enumerator.c#L2890
     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)
 {
diff --git a/test/ruby/test_enumerator.rb b/test/ruby/test_enumerator.rb
index 54dfebb..1e306c3 100644
--- a/test/ruby/test_enumerator.rb
+++ b/test/ruby/test_enumerator.rb
@@ -811,4 +811,49 @@ class TestEnumerator < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_enumerator.rb#L811
       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
-- 
cgit v0.10.2


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]