From 1d4bd229b898671328c2a942b04f08065c640c28 Mon Sep 17 00:00:00 2001 From: Akinori MUSHA Date: Wed, 5 Jun 2019 20:39:21 +0900 Subject: [PATCH] Implement Enumerator::Lazy#eager [Feature #15901] --- NEWS | 3 +++ enumerator.c | 21 +++++++++++++++++++++ test/ruby/test_lazy_enumerator.rb | 8 ++++++++ 3 files changed, 32 insertions(+) diff --git a/NEWS b/NEWS index 710039417a..1350943d28 100644 --- a/NEWS +++ b/NEWS @@ -102,6 +102,9 @@ Enumerator:: New method:: + * Added Enumerator::Lazy#eager that generates a non-lazy enumerator + from a lazy enumerator. [Feature #15901] + * Added Enumerator::Yielder#to_proc so that a Yielder object can be directly passed to another method as a block argument. [Feature #15618] diff --git a/enumerator.c b/enumerator.c index 62534ee241..7a0a17b52f 100644 --- a/enumerator.c +++ b/enumerator.c @@ -1893,6 +1893,26 @@ lazy_to_enum(int argc, VALUE *argv, VALUE self) return lazy; } +static VALUE +lazy_eager_size(VALUE self, VALUE args, VALUE eobj) +{ + return enum_size(self); +} + +/* + * call-seq: + * lzy.eager -> enum + * + * Returns a non-lazy Enumerator converted from the lazy enumerator. + */ + +static VALUE +lazy_eager(VALUE self) +{ + return enumerator_init(enumerator_allocate(rb_cEnumerator), + self, sym_each, 0, 0, lazy_eager_size, Qnil); +} + static VALUE lazyenum_yield(VALUE proc_entry, struct MEMO *result) { @@ -3741,6 +3761,7 @@ InitVM_Enumerator(void) rb_define_method(rb_cLazy, "initialize", lazy_initialize, -1); rb_define_method(rb_cLazy, "to_enum", lazy_to_enum, -1); rb_define_method(rb_cLazy, "enum_for", lazy_to_enum, -1); + rb_define_method(rb_cLazy, "eager", lazy_eager, 0); rb_define_method(rb_cLazy, "map", lazy_map, 0); rb_define_method(rb_cLazy, "collect", lazy_map, 0); rb_define_method(rb_cLazy, "flat_map", lazy_flat_map, 0); diff --git a/test/ruby/test_lazy_enumerator.rb b/test/ruby/test_lazy_enumerator.rb index 72fe1a4a24..caa9a9c713 100644 --- a/test/ruby/test_lazy_enumerator.rb +++ b/test/ruby/test_lazy_enumerator.rb @@ -452,6 +452,14 @@ class TestLazyEnumerator < Test::Unit::TestCase EOS end + def test_lazy_eager + lazy = [1, 2, 3].lazy.map { |x| x * 2 } + enum = lazy.eager + assert_equal Enumerator, enum.class + assert_equal 3, enum.size + assert_equal [1, 2, 3], enum.map { |x| x / 2 } + end + def test_lazy_to_enum lazy = [1, 2, 3].lazy def lazy.foo(*args)