From: Akinori MUSHA Date: 2008-12-03T19:57:10+09:00 Subject: [ruby-dev:37263] Re: [Feature:1.9] Enumerator#inspect --pgp-sign-Multipart_Wed_Dec__3_20:02:56_2008-1 Content-Type: text/plain; charset=ISO-2022-JP At Wed, 3 Dec 2008 18:39:59 +0900, U.Nakamura wrote: > In message "[ruby-dev:37261] Re: [Feature:1.9] Enumerator#inspect" > on Dec.03,2008 18:17:53, wrote: > > |> Enumerator の中身をわかりやすく表示してくれる Enumerator#inspect を > > |> 提供すると便利だと思います。例えばこんな感じ。 > > |> > > |> $ ruby19 -e 'g = (1..1000).each; p g' > > |> # > > |> > > |> 現状は # とかなので、デバッグには不便です。 > > | > > | inspect で実際に回してしまうのは(中身を見るための)副作用として > > |大きすぎ、適切ではない気がします。 > > > > そうですねえ。IOのように再開可能でないEnumerableもありますし > > ねえ。私もあまり賛成できません。わかりやすくするというアイディ > > アには反対ではないんですが。 > > > > Enumeratorの中に最初の3要素を取っておくとかは、たぶんやりすぎ > > でしょうねえ。 > > 実現可能かどうかは考慮してないんですが、実際の中身よりもその > Enumeratorオブジェクトがどこから出てきたのかがわかる方が嬉し > いような気がします。 > 上記の例だと、例えば > # > とか。 まあ、デバッグ用だから見せてしまってもいいかもしれませんね。 (1..100).each_cons(2) => "#" という感じでどうでしょうか。(下に添付) > でも、どんな出方が嬉しいかは、デバッグのやり方によるんでしょ > うねえ。 > なお、私は動いてるスクリプトの中にpを何個かばらまいて挙動を追 > ったりするので、pの有無で(stdoutへの出力以外に)動作が変化して > しまう可能性があるのはあんまり嬉しくないです。 私もそう思います。 Index: enumerator.c =================================================================== --- enumerator.c (revision 20453) +++ enumerator.c (working copy) @@ -545,6 +545,68 @@ enumerator_rewind(VALUE obj) return obj; } +static VALUE +inspect_enumerator(VALUE obj, VALUE dummy, int recur) +{ + struct enumerator *e = enumerator_ptr(obj); + const char *cname = rb_obj_classname(obj); + VALUE eobj, str; + int tainted, untrusted; + + if (recur) { + str = rb_sprintf("#<%s: ...>", cname); + OBJ_TAINT(str); + return str; + } + + eobj = e->obj; + + tainted = OBJ_TAINTED(eobj); + untrusted = OBJ_UNTRUSTED(eobj); + + /* (1..100).each_cons(2) => "#" */ + str = rb_sprintf("#<%s: ", cname); + rb_str_concat(str, rb_inspect(eobj)); + rb_str_buf_cat2(str, ":"); + rb_str_buf_cat2(str, rb_id2name(e->meth)); + + if (e->args) { + int argc = RARRAY_LEN(e->args); + VALUE *argv = RARRAY_PTR(e->args); + + rb_str_buf_cat2(str, "("); + + while (argc--) { + VALUE arg = *argv++; + + rb_str_concat(str, rb_inspect(arg)); + rb_str_buf_cat2(str, argc > 0 ? ", " : ")"); + + if (OBJ_TAINTED(arg)) tainted = Qtrue; + if (OBJ_UNTRUSTED(arg)) untrusted = Qtrue; + } + } + + rb_str_buf_cat2(str, ">"); + + if (tainted) OBJ_TAINT(str); + if (untrusted) OBJ_UNTRUST(str); + return str; +} + +/* + * call-seq: + * e.inspect => string + * + * Create a printable version of e. + */ + +static VALUE +enumerator_inspect(VALUE obj) +{ + return rb_exec_recursive(inspect_enumerator, obj, 0); +} + /* * Yielder */ @@ -779,6 +841,7 @@ Init_Enumerator(void) rb_define_method(rb_cEnumerator, "with_object", enumerator_with_object, 1); rb_define_method(rb_cEnumerator, "next", enumerator_next, 0); rb_define_method(rb_cEnumerator, "rewind", enumerator_rewind, 0); + rb_define_method(rb_cEnumerator, "inspect", enumerator_inspect, 0); rb_eStopIteration = rb_define_class("StopIteration", rb_eIndexError); -- Akinori MUSHA / http://akinori.org/ --pgp-sign-Multipart_Wed_Dec__3_20:02:56_2008-1 Content-Type: application/pgp-signature Content-Transfer-Encoding: 7bit -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (FreeBSD) iEYEABECAAYFAkk2Z2AACgkQkgvvx5/Z4e7bDQCg0nLHA1t9TBzXkwAZC6fvcdPD NHoAoNv/XoelGSzqOmbcJfTWCY5VIHoV =5geM -----END PGP SIGNATURE----- --pgp-sign-Multipart_Wed_Dec__3_20:02:56_2008-1--