ruby-changes:9108
From: knu <ko1@a...>
Date: Thu, 11 Dec 2008 21:14:27 +0900 (JST)
Subject: [ruby-changes:9108] Ruby:r20645 (ruby_1_8): * enumerator.c (enumerator_next, enumerator_rewind),
knu 2008-12-11 21:14:10 +0900 (Thu, 11 Dec 2008) New Revision: 20645 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=20645 Log: * enumerator.c (enumerator_next, enumerator_rewind), lib/generator.rb (Enumerator#rewind): If the enclosed object responds to a "rewind" method, call it. Modified files: branches/ruby_1_8/ChangeLog branches/ruby_1_8/NEWS branches/ruby_1_8/enumerator.c branches/ruby_1_8/lib/generator.rb Index: ruby_1_8/NEWS =================================================================== --- ruby_1_8/NEWS (revision 20644) +++ ruby_1_8/NEWS (revision 20645) @@ -36,6 +36,10 @@ Now can generate an enumerator from a block that defines enumeration instead of an enumerable object. + * Enumerator#rewind + + Now calls the "rewind" method of the enclosed object if defined. + * Hash#default_proc= New method. @@ -117,6 +121,12 @@ * do not raise ShiftingError if an aged file already exists. (no ShiftingError will be raised from 1.2.7, just warn() instead) +=== Compatibility issues (excluding feature bug fixes) + + * Enumerator#rewind + + See above. + == Changes since the 1.8.6 release === Configuration changes Index: ruby_1_8/ChangeLog =================================================================== --- ruby_1_8/ChangeLog (revision 20644) +++ ruby_1_8/ChangeLog (revision 20645) @@ -1,3 +1,9 @@ +Thu Dec 11 21:09:47 2008 Akinori MUSHA <knu@i...> + + * enumerator.c (enumerator_next, enumerator_rewind), + lib/generator.rb (Enumerator#rewind): If the enclosed object + responds to a "rewind" method, call it. + Thu Dec 11 21:07:56 2008 Kouhei Sutou <kou@c...> * lib/rss/maker.rb, lib/rss/maker/0.9.rb, lib/rss/maker/base.rb: Index: ruby_1_8/enumerator.c =================================================================== --- ruby_1_8/enumerator.c (revision 20644) +++ ruby_1_8/enumerator.c (revision 20645) @@ -22,6 +22,7 @@ */ VALUE rb_cEnumerator; static VALUE sym_each; +static ID id_rewind; VALUE rb_eStopIteration; @@ -497,6 +498,18 @@ return memo; } +static int +require_generator() +{ + static int done = 0; + + if (done) + return 0; /* not the first time */ + rb_require("generator"); + done = 1; + return 1; /* the first time */ +} + /* * call-seq: * e.next => object @@ -517,8 +530,15 @@ enumerator_next(obj) VALUE obj; { - rb_require("generator"); - return rb_funcall(obj, rb_intern("next"), 0, 0); + if (require_generator()) { + /* + * Call the new rewind method that the generator library + * redefines. + */ + return rb_funcall(obj, rb_intern("next"), 0, 0); + } else { + rb_raise(rb_eRuntimeError, "unexpected call; the generator library must have failed in redefining this method"); + } } /* @@ -526,14 +546,33 @@ * e.rewind => e * * Rewinds the enumeration sequence by the next method. + * + * If the enclosed object responds to a "rewind" method, it is called. */ static VALUE enumerator_rewind(obj) VALUE obj; { - rb_require("generator"); - return rb_funcall(obj, rb_intern("rewind"), 0, 0); + if (require_generator()) { + /* + * Call the new rewind method that the generator library + * redefines. + */ + return rb_funcall(obj, rb_intern("rewind"), 0, 0); + } else { + /* + * Once the generator library is loaded and the rewind method + * is overridden, this method changes itself to a secret knob + * to rewind the internal object. (black magic!) + */ + struct enumerator *e; + + e = enumerator_ptr(obj); + if (rb_respond_to(e->obj, id_rewind)) + rb_funcall(e->obj, id_rewind, 0); + return obj; + } } /* @@ -815,7 +854,8 @@ rb_define_method(rb_cYielder, "yield", yielder_yield, -2); rb_define_method(rb_cYielder, "<<", yielder_yield, -2); - sym_each = ID2SYM(rb_intern("each")); + sym_each = ID2SYM(rb_intern("each")); + id_rewind = rb_intern("rewind"); /* backward compatibility */ rb_provide("enumerator.so"); Index: ruby_1_8/lib/generator.rb =================================================================== --- ruby_1_8/lib/generator.rb (revision 20644) +++ ruby_1_8/lib/generator.rb (revision 20645) @@ -193,12 +193,18 @@ raise StopIteration, 'iteration reached at end' end + # :nodoc: + alias __orig_rewind rewind + # call-seq: # e.rewind => e # # Rewinds the enumeration sequence by the next method. + # + # If the enclosed object responds to a "rewind" method, it is called. def rewind __generator.rewind + __orig_rewind self end end -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/