From badb86556777cc16d11beb47b38b25997d7aea75 Mon Sep 17 00:00:00 2001 From: knu Date: Thu, 10 Apr 2008 10:52:50 +0000 Subject: * enumerator.c (rb_eStopIteration), eval.c (rb_f_loop), ruby.h: Add a new exception class StopIteration, which breaks Kernel#loop iteration when raised; backported from 1.9. * enumerator.c (enumerator_next, enumerator_rewind): Implement #next and #rewind using the "generator" library. * lib/generator.rb: Implement Enumerable::Enumerator#next and #rewind. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@15954 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- enumerator.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) (limited to 'enumerator.c') diff --git a/enumerator.c b/enumerator.c index e5bf538f0c..fefbc28b34 100644 --- a/enumerator.c +++ b/enumerator.c @@ -23,6 +23,8 @@ VALUE rb_cEnumerator; static VALUE sym_each, sym_call; +VALUE rb_eStopIteration; + static VALUE proc_call(proc, args) VALUE proc; @@ -387,6 +389,45 @@ enumerator_with_index(obj) enumerator_with_index_i, (VALUE)&memo); } +/* + * call-seq: + * e.next => object + * + * Returns the next object in the enumerator, and move the internal + * position forward. When the position reached at the end, internal + * position is rewinded then StopIteration is raised. + * + * Note that enumeration sequence by next method does not affect other + * non-external enumeration methods, unless underlying iteration + * methods itself has side-effect, e.g. IO#each_line. + * + * Caution: Calling this method causes the "generator" library to be + * loaded. + */ + +static VALUE +enumerator_next(obj) + VALUE obj; +{ + rb_require("generator"); + return rb_funcall(obj, rb_intern("next"), 0, 0); +} + +/* + * call-seq: + * e.rewind => e + * + * Rewinds the enumeration sequence by the next method. + */ + +static VALUE +enumerator_rewind(obj) + VALUE obj; +{ + rb_require("generator"); + return rb_funcall(obj, rb_intern("rewind"), 0, 0); +} + void Init_Enumerator() { @@ -406,6 +447,10 @@ Init_Enumerator() rb_define_method(rb_cEnumerator, "initialize_copy", enumerator_init_copy, 1); rb_define_method(rb_cEnumerator, "each", enumerator_each, 0); rb_define_method(rb_cEnumerator, "with_index", enumerator_with_index, 0); + rb_define_method(rb_cEnumerator, "next", enumerator_next, 0); + rb_define_method(rb_cEnumerator, "rewind", enumerator_rewind, 0); + + rb_eStopIteration = rb_define_class("StopIteration", rb_eIndexError); sym_each = ID2SYM(rb_intern("each")); sym_call = ID2SYM(rb_intern("call")); -- cgit v1.2.3