StopIteration#result e$B$r?7@_$9$k$N$O$I$&$G$7$g$&e(B?
e$B0J2<$NNc$G!"e(BStopIteration#result e$B$O!"e(B(e$B%V%m%C%/$D$-$Ne(B)
Array#each e$B$NJV$jCM$rJV$7$^$9!#e(B
a = [1,2,3]
e = a.enum_for(:each)
p e.next #=> 1
p e.next #=> 2
p e.next #=> 3
e.next rescue p $!.result #=> [1, 2, 3]
Array#each e$B$O$=$NG[Ns<+BN$rJV$9$N$G!"e(B$!.result e$B$Oe(B [1, 2, 3]
e$B$K$J$C$F$$$^$9!#e(B
Enumerator e$B$G30It%$%F%l!<%?$r:n$C$F;H$&$H!"FbIt%$%F%l!<%?$re(B
Fiber e$BFb$GF0$+$7$^$9!#e(Beach e$B$J$I$NFbIt%$%F%l!<%?$O=*N;$9$k$He(B
e$B$-$K2?$+CM$rJV$9$o$1$G$9$,!“8=:_$O$=$NCM$rF@$kJ}K!$,$”$j$^$;e(B
e$B$s!#e(B
e$B$^$!!"D>@\2?$+$KLr$KN)$D$+$H$$$&$H5?$o$7$$5$$,$7$^$9$,!“30Ite(B
e$B%$%F%l!<%?$r;H$C$FFbIt%$%F%l!<%?$r<BAu$9$k$H$-$K8e<T$NJV$jCMe(B
e$B$rA0<T$+$i;XDj$G$-$k$H$+!”$A$g$C$H%a%?$J$3$H$r$d$m$&$H$7$?$He(B
e$B$-$K;H$($k5$$,$7$^$9!#e(B
StopIteration#result e$B$O30It%$%F%l!<%?$HFbIt%$%F%l!<%?$N5!G=e(B
e$B$N$:$l$r=|5n$9$k!"$H$b$$$($^$9!#40A4@-$H$$$&$+!#e(B
e$B$H$$$&$o$1$G$I$&$G$7$g$&$+!#e(B
% svn diff --diff-cmd diff -x ‘-u -p’
Index: enumerator.c
— enumerator.c (revision 24578)
+++ enumerator.c (working copy)
@@ -33,7 +33,7 @@ struct enumerator {
VALUE fib;
VALUE dst;
VALUE lookahead;
- VALUE no_next;
- VALUE stop_exc;
};
static VALUE rb_cGenerator, rb_cYielder;
@@ -284,7 +284,7 @@ enumerator_init(VALUE enum_obj, VALUE ob
ptr->fib = 0;
ptr->dst = Qnil;
ptr->lookahead = Qundef;
- ptr->no_next = Qfalse;
-
ptr->stop_exc = Qfalse;
return enum_obj;
}
@@ -506,14 +506,23 @@ next_ii(VALUE i, VALUE obj, int argc, VA
return Qnil;
}
+static VALUE
+stop_result(VALUE self)
+{
- return rb_attr_get(self, rb_intern(“result”));
+}
static VALUE
next_i(VALUE curr, VALUE obj)
{
struct enumerator *e = enumerator_ptr(obj);
VALUE nil = Qnil;
- VALUE result;
- rb_block_call(obj, id_each, 0, 0, next_ii, obj);
- e->no_next = Qtrue;
- result = rb_block_call(obj, id_each, 0, 0, next_ii, obj);
- e->stop_exc = rb_exc_new2(rb_eStopIteration, “iteration reached at
end”); - rb_ivar_set(e->stop_exc, rb_intern(“result”), result);
return rb_fiber_yield(1, &nil);
}
@@ -552,8 +561,8 @@ enumerator_next(VALUE obj)
return v;
}
- if (e->no_next)
- rb_raise(rb_eStopIteration, “iteration reached at end”);
-
if (e->stop_exc)
-
rb_exc_raise(e->stop_exc);
curr = rb_fiber_current();
@@ -562,11 +571,11 @@ enumerator_next(VALUE obj)
}
v = rb_fiber_resume(e->fib, 1, &curr);
- if (e->no_next) {
- if (e->stop_exc) {
e->fib = 0;
e->dst = Qnil;
e->lookahead = Qundef;
- rb_raise(rb_eStopIteration, “iteration reached at end”);
- rb_exc_raise(e->stop_exc);
}
return v;
}
@@ -617,7 +626,7 @@ enumerator_rewind(VALUE obj)
e->fib = 0;
e->dst = Qnil;
e->lookahead = Qundef;
- e->no_next = Qfalse;
- e->stop_exc = Qfalse;
return obj;
}
@@ -915,6 +924,7 @@ Init_Enumerator(void)
rb_define_method(rb_cEnumerator, “inspect”, enumerator_inspect, 0);
rb_eStopIteration = rb_define_class("StopIteration",
rb_eIndexError);
-
rb_define_method(rb_eStopIteration, “result”, stop_result, 0);
/* Generator */
rb_cGenerator = rb_define_class_under(rb_cEnumerator, “Generator”,
rb_cObject);
Index: test/ruby/test_enumerator.rb
===================================================================
— test/ruby/test_enumerator.rb (revision 24578)
+++ test/ruby/test_enumerator.rb (working copy)
@@ -152,5 +152,14 @@ class TestEnumerator < Test::Unit::TestC
assert_raise(StopIteration) { e.next }
assert_raise(StopIteration) { e.next }
end -
def test_stop_result
-
a = [1]
-
res = a.each {}
-
e = a.each
-
assert_equal(1, e.next)
-
exc = assert_raise(StopIteration) { e.next }
-
assert_equal(res, exc.result)
-
end
end