[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]