[#39052] Fwd: [redmine4ruby-lang:253] [Bug #1914] ruby-1.9.1-p243 failed to build from source on aix 5.3 with gcc 4.2.0 — Yugui <yugui@...>

Redmine管理用プロジェクトに報告されてしまったので転送します。

12 messages 2009/08/09
[#39264] Re: Fwd: [redmine4ruby-lang:253] [Bug #1914] ruby-1.9.1-p243 failed to build from source on aix 5.3 with gcc 4.2.0 — Yutaka Kanemoto <kinpoco@...> 2009/09/08

金本と申します。

[#39107] [Bug #1952] cannot stop with Ctrl+C — Usaku NAKAMURA <redmine@...>

Bug #1952: cannot stop with Ctrl+C

14 messages 2009/08/18

[#39167] [Bug #2000] Change the license to "GPLv2+ or Ruby's original". — Mamoru Tasaka <redmine@...>

Bug #2000: Change the license to "GPLv2+ or Ruby's original".

11 messages 2009/08/26

[#39193] Re: [ruby-cvs:31917] Ruby:r24699 (trunk): * lib/tmpdir.rb (Dir.mktmpdir): removed thread race condition. — Tanaka Akira <akr@...>

In article <200908281827.n7SIRbaX003476@ci.ruby-lang.org>,

16 messages 2009/08/29
[#39194] Re: [ruby-cvs:31917] Ruby:r24699 (trunk): * lib/tmpdir.rb (Dir.mktmpdir): removed thread race condition. — Nobuyoshi Nakada <nobu@...> 2009/08/29

なかだです。

[#39195] Re: [ruby-cvs:31917] Ruby:r24699 (trunk): * lib/tmpdir.rb (Dir.mktmpdir): removed thread race condition. — Tanaka Akira <akr@...> 2009/08/29

In article <4a988633.9553f10a.4496.483e@mx.google.com>,

[#39196] Re: [ruby-cvs:31917] Ruby:r24699 (trunk): * lib/tmpdir.rb (Dir.mktmpdir): removed thread race condition. — Nobuyoshi Nakada <nobu@...> 2009/08/29

なかだです。

[#39197] Re: [ruby-cvs:31917] Ruby:r24699 (trunk): * lib/tmpdir.rb (Dir.mktmpdir): removed thread race condition. — Tanaka Akira <akr@...> 2009/08/29

In article <4a989f76.1602be0a.3de4.1131@mx.google.com>,

[#39198] Re: [ruby-cvs:31917] Ruby:r24699 (trunk): * lib/tmpdir.rb (Dir.mktmpdir): removed thread race condition. — Yukihiro Matsumoto <matz@...> 2009/08/29

まつもと ゆきひろです

[#39206] Re: [ruby-cvs:31917] Ruby:r24699 (trunk): * lib/tmpdir.rb (Dir.mktmpdir): removed thread race condition. — Nobuyoshi Nakada <nobu@...> 2009/08/31

なかだです。

[ruby-dev:39109] StopIteration#result

From: Tanaka Akira <akr@...>
Date: 2009-08-18 15:55:57 UTC
List: ruby-dev #39109
StopIteration#result を新設するのはどうでしょう?

以下の例で、StopIteration#result は、(ブロックつきの)
Array#each の返り値を返します。

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 はその配列自体を返すので、$!.result は [1, 2, 3]
になっています。

Enumerator で外部イテレータを作って使うと、内部イテレータを
Fiber 内で動かします。each などの内部イテレータは終了すると
きに何か値を返すわけですが、現在はその値を得る方法がありませ
ん。

まぁ、直接何かに役に立つかというと疑わしい気がしますが、外部
イテレータを使って内部イテレータを実装するときに後者の返り値
を前者から指定できるとか、ちょっとメタなことをやろうとしたと
きに使える気がします。

StopIteration#result は外部イテレータと内部イテレータの機能
のずれを除去する、ともいえます。完全性というか。

というわけでどうでしょうか。

% 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
 
-- 
[田中 哲][たなか あきら][Tanaka Akira]

In This Thread

Prev Next