OpenStruct の inspectの謎
言語処理系とかでpritty printを作ってる人にとっては、べつに謎でもなんでもないんだろうな。
このinspectは組み込みのpメソッドで出力するときに呼ばれるメソッド。OpenStructの場合はこれ。
def inspect str = "#<#{self.class}" Thread.current[InspectKey] ||= [] if Thread.current[InspectKey].include?(self) then str << " ..." else first = true for k,v in @table str << "," unless first first = false Thread.current[InspectKey] << v begin str << " #{k}=#{v.inspect}" ensure Thread.current[InspectKey].pop end end end str << ">" end
何でThread.currentを使っているのか、何でinclude?でselfがいるかどうかを調べているのかが1時間くらい考えてもわからなかった。
threadに何か関係するのか?とか、ぜんぜん違う見方をしていた。
このThread.currentは要素が入れ子になっているときのために使うものだった。同じスレッドで共有しているのでv.inspectのvが自分自身でも再帰がとまるって仕組み。標準のものはよくできてるなぁ。
irb(main):002:0> require "ostruct" require "ostruct" => true irb(main):003:0> a = OpenStruct.new a = OpenStruct.new => #<OpenStruct> irb(main):004:0> a a => #<OpenStruct> irb(main):005:0> a.name = "hoge" a.name = "hoge" => "hoge" irb(main):006:0> a a => #<OpenStruct name="hoge"> irb(main):008:0> a.self = a a.self = a => #<OpenStruct name="hoge", self=#<OpenStruct ...>> irb(main):009:0>