From: Yusuke ENDOH Date: 2009-11-11T23:50:47+09:00 Subject: [ruby-dev:39663] Re: [Bug:trunk] Enumerator.new {|y| y << 1 << 2 << 3 } 遠藤です。 2009年11月11日22:54 Tanaka Akira : > In article , > Yusuke ENDOH writes: > >> 今 Yielder#<< は Yielder#yield の alias になっていますが、yield は >> 元の挙動のまま、Yielder#<< だけ常に self を返すようにしてもいいで >> しょうか。 > > あぁ、それは妥当だと思います。 ありがとうございます。それではコミットします。 > それはそれとして、ドキュメントは必要でしょうねぇ。 Enumerator::Yielder と Enumerator::Generator は全部 nodoc だったので、 あわせて適当に書いてみました。これもコミットしようと思います。 書いていて気がついたんですが、Generator#each は self ではなく proc の 戻り値を返すようです。意図的なんでしょうか。 g = Enumerator::Generator.new {|y| y << 1 << 2 << 3; :foo } p g.each {} #=> :foo まあ、Generator を直接使うことは普通はないので、問題になることはない のかもしれませんが。 diff --git a/enumerator.c b/enumerator.c index e341c07..e8e147a 100644 --- a/enumerator.c +++ b/enumerator.c @@ -994,7 +994,19 @@ yielder_init(VALUE obj, VALUE proc) return obj; } -/* :nodoc: */ +/* + * call-seq: + * Enumerator::Yielder.new {|x| block } => new_yielder + * + * Returns a new yielder encapsulating a given proc. + * proc is called with arguments that the yielder receives by + * Enumerator::Yielder#yield or <<. + * + * y = Enumerator::Yielder.new {|x| p x } + * y << 1 #=> 1 + * y << 2 #=> 2 + * y << 3 #=> 3 + */ static VALUE yielder_initialize(VALUE obj) { @@ -1003,7 +1015,18 @@ yielder_initialize(VALUE obj) return yielder_init(obj, rb_block_proc()); } -/* :nodoc: */ +/* + * call-seq: + * yielder.yield(val) => value that proc returns + * + * Invokes the encapsulated proc and passes val as an argument. + * Returns value that the proc returns. + * + * y = Enumerator::Yielder.new {|x| x * 10 } + * p y.yield(1) #=> 10 + * p y.yield(2) #=> 20 + * p y.yield(3) #=> 30 + */ static VALUE yielder_yield(VALUE obj, VALUE args) { @@ -1012,6 +1035,22 @@ yielder_yield(VALUE obj, VALUE args) return rb_proc_call(ptr->proc, args); } +/* + * call-seq: + * yielder << val => self + * + * Invokes the encapsulated proc and passes val as an argument. + * Returns self. + * + * y = Enumerator::Yielder.new {|x| p x } + * y << 1 << 2 << 3 #=> 1, 2, 3 + */ +static VALUE yielder_yield_push(VALUE obj, VALUE args) +{ + yielder_yield(obj, args); + return obj; +} + static VALUE yielder_yield_i(VALUE obj, VALUE memo, int argc, VALUE *argv) { @@ -1092,7 +1131,18 @@ generator_init(VALUE obj, VALUE proc) VALUE rb_obj_is_proc(VALUE proc); -/* :nodoc: */ +/* + * call-seq: + * Enumerator::Generator.new {|y| block } => new_generator + * Enumerator::Generator.new(proc) => new_generator + * + * Returns a new generator encapsulating a given proc. + * proc receives an instance of Enumerator::Yielder. The generator + * enumerates a sequence of values that the yielder receives by + * Enumerator::Yielder#yield or <<. + * + * Enumerator::Generator.new {|y| y << 1 << 2 << 3 }.to_a #=> [1, 2, 3] + */ static VALUE generator_initialize(int argc, VALUE *argv, VALUE obj) { @@ -1137,7 +1187,14 @@ generator_init_copy(VALUE obj, VALUE orig) return obj; } -/* :nodoc: */ +/* call-seq: + * generator.each {|x| block } => value that proc returns + * + * Enumerates the sequence of the generator. + * + * g = Enumerator::Generator.new {|y| y << 1 << 2 << 3 } + * g.each {|x| p x } #=> 1, 2, 3 + */ static VALUE generator_each(VALUE obj) { @@ -1228,7 +1285,7 @@ Init_Enumerator(void) rb_define_alloc_func(rb_cYielder, yielder_allocate); rb_define_method(rb_cYielder, "initialize", yielder_initialize, 0); rb_define_method(rb_cYielder, "yield", yielder_yield, -2); - rb_define_method(rb_cYielder, "<<", yielder_yield, -2); + rb_define_method(rb_cYielder, "<<", yielder_yield_push, -2); id_rewind = rb_intern("rewind"); id_each = rb_intern("each"); -- Yusuke ENDOH