http://www.atdot.net/~ko1/diary/200610.html#d10 を見てENDとat_exitの違いが気になったので調べてみる。
3.times {|n|
at_exit {
puts "at_exit #{n}"
3.times {|m|
at_exit {
puts "at_exit #{n} at_exit #{m}"
}
}
}
END {
puts "END #{n}"
3.times {|m|
END {
puts "END #{n} END #{m}"
}
}
}
}
実行結果:
ruby 1.8.2 (2005-04-11) [i386-linux]
at_exit 2
at_exit 1
END 0
at_exit 0
at_exit 0 at_exit 2
at_exit 0 at_exit 1
at_exit 0 at_exit 0
END 0 END 0
at_exit 1 at_exit 2
at_exit 1 at_exit 1
at_exit 1 at_exit 0
at_exit 2 at_exit 2
at_exit 2 at_exit 1
at_exit 2 at_exit 0
他にはENDはメソッドの中では使えないとか。
- まず grep END *.* してみたらヒットしすぎ。
- grep END lex.c parse.yというあたりで探してみるとklENDらしいとわかる。
- parse.yのklENDのところをページャーで見てNEW_POSTEXEがポイントっぽい気がしたので、
- grep NEW_POSTEXE *.*で「node.h:#define NEW_POSTEXE() NEW_NODE(NODE_POSTEXE,0,0,0)」
- grep NODE_POSTEXE *.*でeval.cを見れば良さそうと気づく。
- eval.cのcase NODE_POSTEXEでrb_f_END()が実際の処理っぽい。
- grep rb_f_END *.*してみたら、eval.cの中にrb_f_ENDがあった。
- 肝はrb_set_end_procっぽい。すぐ下にrb_f_at_exit()があって、その中でもrb_set_end_procを呼んでいる。
- rb_set_end_procの仲まで見ずにENDとat_exitで登録したブロックは別々のリストではなく混ざったリストで実行されるらしいとわかる。
■ ENDが使えないところ
class END
end
END()
class Hoge
def END
puts "END method"
end
end
Hoge.new.END()