aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--enumerator.c36
-rw-r--r--test/ruby/test_enumerator.rb5
3 files changed, 45 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index 1baba4f7d0..e405299063 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,7 @@
-Wed Jul 20 17:39:11 2016 Nobuyoshi Nakada <nobu@ruby-lang.org>
+Wed Jul 20 17:44:07 2016 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * enumerator.c (lazy_uniq): new method Enumerator::Lazy#uniq.
+ [Feature #11090]
* enum.c (enum_uniq): new method Enumerable#uniq.
[Feature #11090]
diff --git a/enumerator.c b/enumerator.c
index a59473a88c..2d692e537f 100644
--- a/enumerator.c
+++ b/enumerator.c
@@ -1959,6 +1959,41 @@ lazy_drop_while(VALUE obj)
}
static VALUE
+lazy_uniq_i(VALUE i, VALUE hash, int argc, const VALUE *argv, VALUE yielder)
+{
+ if (rb_hash_add_new_element(hash, i, Qfalse))
+ return Qnil;
+ return rb_funcall2(yielder, id_yield, argc, argv);
+}
+
+static VALUE
+lazy_uniq_func(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash))
+{
+ VALUE yielder = (--argc, *argv++);
+ i = rb_enum_values_pack(argc, argv);
+ return lazy_uniq_i(i, hash, argc, argv, yielder);
+}
+
+static VALUE
+lazy_uniq_iter(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash))
+{
+ VALUE yielder = (--argc, *argv++);
+ i = rb_yield_values2(argc, argv);
+ return lazy_uniq_i(i, hash, argc, argv, yielder);
+}
+
+static VALUE
+lazy_uniq(VALUE obj)
+{
+ rb_block_call_func *const func =
+ rb_block_given_p() ? lazy_uniq_iter : lazy_uniq_func;
+ VALUE hash = rb_obj_hide(rb_hash_new());
+ return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
+ func, hash),
+ 0, 0);
+}
+
+static VALUE
lazy_super(int argc, VALUE *argv, VALUE lazy)
{
return enumerable_lazy(rb_call_super(argc, argv));
@@ -2074,6 +2109,7 @@ InitVM_Enumerator(void)
rb_define_method(rb_cLazy, "slice_before", lazy_super, -1);
rb_define_method(rb_cLazy, "slice_after", lazy_super, -1);
rb_define_method(rb_cLazy, "slice_when", lazy_super, -1);
+ rb_define_method(rb_cLazy, "uniq", lazy_uniq, 0);
rb_define_alias(rb_cLazy, "force", "to_a");
diff --git a/test/ruby/test_enumerator.rb b/test/ruby/test_enumerator.rb
index 3cb9dc789f..bd6b7fa669 100644
--- a/test/ruby/test_enumerator.rb
+++ b/test/ruby/test_enumerator.rb
@@ -646,5 +646,10 @@ class TestEnumerator < Test::Unit::TestCase
e.next
assert_raise(StopIteration) { e.peek }
end
+
+ def test_uniq
+ assert_equal([1, 2, 3, 4, 5, 10],
+ (1..Float::INFINITY).lazy.uniq{|x| (x**2) % 10 }.first(6))
+ end
end