From: nobu.nakada@... Date: 2000-01-24T19:35:49+09:00 Subject: [ruby-dev:9008] [PATCH] Array#flatten! for recursive array なかだです。 b = [a = []]; a << b; a.inspect が SystemStackError になったりする(rb_protect_inspect(), rb_ary_includes() から呼ばれる a == b のところでお互いのシッポを 追っかけあってるような状態)ので、パッチです。 a = []; a << a; a.flatten! が返って来なかったりするのも一緒に変更しちゃってますが、あるいは こういう再帰的な構造に対して flatten! を使おうというがそもそも間 違ってるんでしょうか。いっそ raise すべき? diff -ru2p dist/array.c build/array.c --- dist/array.c Tue Jan 18 23:10:12 2000 +++ build/array.c Mon Jan 24 19:01:54 2000 @@ -791,6 +791,6 @@ rb_protect_inspect(func, obj, arg) { struct inspect_arg iarg; - VALUE inspect_tbl; + VALUE id; if (!inspect_key) { @@ -802,8 +802,9 @@ rb_protect_inspect(func, obj, arg) rb_thread_local_aset(rb_thread_current(), inspect_key, inspect_tbl); } - if (rb_ary_includes(inspect_tbl, obj)) { + id = rb_obj_id(obj); + if (rb_ary_includes(inspect_tbl, id)) { return (*func)(obj, arg); } - rb_ary_push(inspect_tbl, obj); + rb_ary_push(inspect_tbl, id); iarg.func = func; iarg.arg1 = obj; @@ -822,5 +823,5 @@ rb_inspecting_p(obj) inspect_tbl = rb_thread_local_aref(rb_thread_current(), inspect_key); if (NIL_P(inspect_tbl)) return Qfalse; - return rb_ary_includes(inspect_tbl, obj); + return rb_ary_includes(inspect_tbl, rb_obj_id(obj)); } @@ -1501,4 +1502,5 @@ rb_ary_flatten_bang(ary) long i; int mod = 0; + VALUE flattening = Qnil; rb_ary_modify(ary); @@ -1506,4 +1508,18 @@ rb_ary_flatten_bang(ary) VALUE ary2 = RARRAY(ary)->ptr[i]; if (TYPE(ary2) == T_ARRAY) { + if (ary == ary2) { + ary2 = Qnil; + } else { + VALUE id; + if (NIL_P(flattening)) { + flattening = rb_ary_new(); + } + id = rb_obj_id(ary2); + if (rb_ary_includes(flattening, id)) { + ary2 = Qnil; + } else { + rb_ary_push(flattening, id); + } + } rb_ary_replace(ary, i--, 1, ary2); mod = 1; -- そうだ 強気に ちょっと インチキに☆彡 中田 "Bugるくらいがちょうどいいかも;-)" 伸悦