ブログトップ 記事一覧 ログイン 無料ブログ開設

それはそれ。これはこれ。 このページをアンテナに追加 RSSフィード

2003 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2004 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2005 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2006 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 03 | 04 | 05 | 06 | 07 | 09 | 10 | 11 | 12 |
2012 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 11 | 12 |
2013 | 01 | 02 | 04 | 05 | 07 | 08 | 10 | 11 | 12 |
2014 | 02 | 03 | 07 | 08 | 09 | 10 | 11 | 12 |
2015 | 01 | 02 | 03 | 05 | 06 | 07 | 11 |
2016 | 07 |
2017 | 01 | 03 | 06 | 07 | 11 |
2018 | 05 | 07 | 08 | 09 | 10 |

2012-03-08(木)

[] to_sString を返さなかったら?  to_s が String を返さなかったら?を含むブックマーク  to_s が String を返さなかったら?のブックマークコメント

puts すると String じゃないと to_s が呼ばれるが、to_sString を返さなかったらどうなるか?さらto_s が呼ばれて無限ループと言うことは無いだろうけど。

class Foo
  def to_s
    self
  end
end

puts Foo.new #=> #<Foo:0x0000000dcc2858>

Foo#to_sString じゃないと Object#to_s が呼ばれているのか?

class Object
  def to_s
    puts "call Object#to_s"
    nil
  end
end
class Foo
  def to_s
    puts "call Foo#to_s"
    self
  end
end

puts Foo.new #=> call Foo#to_s
                 #<Foo:0x0000000ac84948>

どうもそういうわけでもない。ということで、ソースを見てみる。まずは、IO#write を見る。

static VALUE
io_write(VALUE io, VALUE str, int nosync)
{
(中略)
    str = rb_obj_as_string(str);
(中略)

どうも、ここで String に変換しているようだ。

VALUE
rb_obj_as_string(VALUE obj)
{
    VALUE str;

    if (TYPE(obj) == T_STRING) {
    return obj;
    }
    str = rb_funcall(obj, id_to_s, 0);
    if (TYPE(str) != T_STRING)
    return rb_any_to_s(obj);
    if (OBJ_TAINTED(obj)) OBJ_TAINT(str);
    return str;
}

String かどうか調べて、String じゃないとメソッドto_s を呼んで、その結果が String かどうかまた調べて、String じゃないとこんどはCの関数 rb_any_to_s() を呼んでいる。

VALUE
rb_any_to_s(VALUE obj)
{
    const char *cname = rb_obj_classname(obj);
    VALUE str;

    str = rb_sprintf("#<%s:%p>", cname, (void*)obj);
    OBJ_INFECT(str, obj);

    return str;
}

と、ここで有無を言わせず文字列に変換している。

トラックバック - http://d.hatena.ne.jp/otn/20120308