From: Yusuke ENDOH Date: 2008-12-02T23:59:52+09:00 Subject: [ruby-dev:37248] [Feature:1.9] Enumerator#inspect 遠藤です。 Enumerator の中身をわかりやすく表示してくれる Enumerator#inspect を 提供すると便利だと思います。例えばこんな感じ。 $ ruby19 -e 'g = (1..1000).each; p g' # 現状は # とかなので、デバッグには不便です。 以下はたたき台のパッチです。 Index: enumerator.c =================================================================== --- enumerator.c (revision 20448) +++ enumerator.c (working copy) @@ -545,7 +545,69 @@ return obj; } +static VALUE +inspect_enumerator_i(VALUE val, VALUE *memo) +{ + VALUE str = memo[0]; + if (memo[1] >= 3) { + rb_str_buf_cat2(str, ", ...(snipped)"); + rb_iter_break(); + } + if (memo[1] > 0) rb_str_buf_cat2(str, ", "); + rb_str_buf_append(str, rb_inspect(val)); + memo[1]++; + if (OBJ_TAINTED(val)) memo[2] = Qtrue; + if (OBJ_UNTRUSTED(val)) memo[3] = Qtrue; + return Qnil; +} + +static VALUE +inspect_enumerator(VALUE obj, VALUE dummy, int recur) +{ + const char *cname = rb_obj_classname(obj); + struct enumerator *e; + int argc = 0; + VALUE *argv = 0; + VALUE str; + VALUE memo[4]; + + if (recur) { + str = rb_sprintf("#<%s:[...]>", cname); + OBJ_TAINT(str); + return str; + } + + memo[0] = str = rb_sprintf("#<%s:[", cname); + memo[1] = (VALUE)0; + memo[2] = OBJ_TAINTED(obj); + memo[3] = OBJ_UNTRUSTED(obj); + e = enumerator_ptr(obj); + if (e->args) { + argc = RARRAY_LEN(e->args); + argv = RARRAY_PTR(e->args); + } + rb_block_call(e->obj, e->meth, argc, argv, + inspect_enumerator_i, (VALUE)memo); + rb_str_buf_cat2(str, "]>"); + if (memo[2]) OBJ_TAINT(str); + if (memo[3]) OBJ_UNTRUST(str); + return str; +} + /* + * call-seq: + * e.inspect => "#" + * + * Create a printable version of e. + */ + +static VALUE +enumerator_inspect(VALUE obj) +{ + return rb_exec_recursive(inspect_enumerator, obj, 0); +} + +/* * Yielder */ static void @@ -779,6 +841,7 @@ 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); Index: lib/pp.rb =================================================================== --- lib/pp.rb (revision 20448) +++ lib/pp.rb (working copy) @@ -339,6 +339,27 @@ end end +class Enumerator + def pretty_print(q) + s = self.class.to_s + q.group(s.size + 3, '#<' + s + ':', ']>') { + idx = 0 + q.seplist(take(4)) {|v| + if idx < 3 + q.pp v + else + q.text "...(snipped)" + end + idx += 1 + } + } + end + + def pretty_print_cycle(q) + q.text('#<' + self.class.to_s + ':[...]') + end +end + class Hash def pretty_print(q) q.pp_hash self -- Yusuke ENDOH