!が着いたメソッド探し
ObjectSpaceを使って、!が着いたメソッド探しをしましょう!(←これは感嘆符)
name = Array.new ObjectSpace.each_object(Class) do |c| c.instance_methods(false).each do |mname| # super not included if /\!$/ =~ mname name << "i #{c.to_s}##{mname}" end end c.singleton_methods.each do |mname| if /\!$/ =~ mname name << "c #{c.to_s}.#{mname}" end end end name.sort.each do |s| puts s end
実行結果です。意外と少ないですね。頭にcが付いているのは特異メソッド(クラスの場合にはクラスメソッド)です。
c Gem::SourceIndex.terminate_interaction! c NameError::message.! c Rational.new! i Array#collect! i Array#compact! i Array#flatten! i Array#map! i Array#reject! i Array#reverse! i Array#slice! i Array#sort! i Array#uniq! i Bignum#power! i Fixnum#power! i Gem::SourceIndex#refresh! i Gem::StreamUI#terminate_interaction! i Hash#merge! i Hash#reject! i OpenSSL::BN#clear_bit! i OpenSSL::BN#mask_bits! i OpenSSL::BN#set_bit! i OpenSSL::PKey::DH#generate_key! i String#capitalize! i String#chomp! i String#chop! i String#delete! i String#downcase! i String#gsub! i String#lstrip! i String#next! i String#reverse! i String#rstrip! i String#slice! i String#squeeze! i String#strip! i String#sub! i String#succ! i String#swapcase! i String#tr! i String#tr_s! i String#upcase!
疑問:上記に出てくるNameError::message.!って何でしょうね。riやrefeでは見つけられませんでした。
追記:(最近何かと関わりの多い)ささださんからコメントで、「Class→Module」と「grep ! error.c」と「puts name.sort」というヒントをいただきました。
C:\ruby\src\ruby-1.8.4>grep \"!\" error.c error.c: rb_define_singleton_method(rb_cNameErrorMesg, "!", name_err_mesg_new, 3);
ふうむ…。
ま、とりあえず、ささださんからのコメント反映したスクリプトです。
name = Array.new ObjectSpace.each_object(Module) do |c| c.instance_methods(false).each do |mname| # super not included if /\!$/ =~ mname name << "i #{c.to_s}##{mname}" end end c.singleton_methods.each do |mname| if /\!$/ =~ mname name << "c #{c.to_s}.#{mname}" end end end puts name.sort
追記:id:sumimさんから、ループ中でifでチェックするのではなく、grepを噛ませる方法を教えていただきました。感謝♪
name = Array.new ObjectSpace.each_object(Module) do |c| c.instance_methods(false).grep(/\!$/) do |mname| # super not included name << "i #{c.to_s}##{mname}" end c.singleton_methods.grep(/\!$/) do |mname| name << "c #{c.to_s}.#{mname}" end end puts name.sort
追記:なかださんから「NameError::message.!はNameErrorのmarshalのために内部的に使うもの」という情報をいただきました。感謝です♪