[#37248] [Feature:1.9] Enumerator#inspect — "Yusuke ENDOH" <mame@...>

遠藤です。

12 messages 2008/12/02

[#37337] [Feature #841] Object#self — "rubikitch ." <redmine@...>

Feature #841: Object#self

13 messages 2008/12/09

[#37513] Current status of 1.9.1 RC1's issues — "Yugui (Yuki Sonoda)" <yugui@...>

Hi, folks

14 messages 2008/12/20
[#37516] Re: Current status of 1.9.1 RC1's issues — Masatoshi SEKI <m_seki@...> 2008/12/20

咳といいます。

[#37576] [BUG:trunk] encoding for stdio's — "Yugui (Yuki Sonoda)" <yugui@...>

Yuguiです。

11 messages 2008/12/24

[ruby-dev:37263] Re: [Feature:1.9] Enumerator#inspect

From: "Akinori MUSHA" <knu@...>
Date: 2008-12-03 10:57:10 UTC
List: ruby-dev #37263
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, <matz@ruby-lang.org> wrote:
> > |> Enumerator の中身をわかりやすく表示してくれる Enumerator#inspect を
> > |> 提供すると便利だと思います。例えばこんな感じ。
> > |>
> > |> $ ruby19 -e 'g = (1..1000).each; p g'
> > |> #<Enumerator:[1, 2, 3, ...(snipped)]>
> > |>
> > |> 現状は #<Enumerator:0x8269654> とかなので、デバッグには不便です。
> > |
> > | inspect で実際に回してしまうのは(中身を見るための)副作用として
> > |大きすぎ、適切ではない気がします。
> >
> > そうですねえ。IOのように再開可能でないEnumerableもありますし
> > ねえ。私もあまり賛成できません。わかりやすくするというアイディ
> > アには反対ではないんですが。
> >
> > Enumeratorの中に最初の3要素を取っておくとかは、たぶんやりすぎ
> > でしょうねえ。
>
> 実現可能かどうかは考慮してないんですが、実際の中身よりもその
> Enumeratorオブジェクトがどこから出てきたのかがわかる方が嬉し
> いような気がします。
> 上記の例だと、例えば
>   #<Enumerator:Range#each>
> とか。

まあ、デバッグ用だから見せてしまってもいいかもしれませんね。

(1..100).each_cons(2) => "#<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) => "#<Enumerator: 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 <i>e</i>.
+ */
+
+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/

In This Thread