From: rubikitch Date: 2006-08-30T14:43:59+09:00 Subject: [ruby-list:42769] Re: ?がメソッド名の途中にあるのはNG? From: Daisuke Yamazaki Subject: [ruby-list:42768] Re: ?がメソッド名の途中にあるのはNG? Date: Wed, 30 Aug 2006 14:13:29 +0900 るびきちです。 > ↓こんな感じにかければうれしかった. > irb(main):001:0> Array.new.inject.help irbに渡す前に preprocessor を通すことを思い出しました。 たとえば Array.new.inject ? のように / \?$/ な行を Array.new.help(:inject) と置き換えて解釈させるのです。 これは拙作irbshのirb拡張部分です。 たとえば foo () 1 を def foo() 1 end と同じ働きにさせたりなど拡張文法を定義しています。 この拡張はirbshと独立しているので試してみては? FILTERS_DEFAULTは勝手に定義してしまってください。 require 'irb/ruby-lex' require 'test/unit/assertions' require 'stringio' $nullout = StringIO.new $debugout = $nullout class Module public :define_method end module IRB module InputFilter extend Test::Unit::Assertions FilterNotFound = Class.new(RuntimeError) FILTERS_DEFAULT = [ [ /^cd +(.+?)\s*$/, proc{|l,m| "irbsh_cd %q[#{m[1]}]\n"}], [ /^ +(cd|pushd)\s*$/, proc{|l,m| "irbsh_#{m[1]}\n"}], [ /^ +(cd|pushd) +(.+)\s*$/, proc{|l,m| "irbsh_#{m[1]} %q[#{m[2]}]\n"}], [ /;$/, proc{|l,m| "Irbsh.disable_output;#{m.pre_match}\n" }], [ /\$$/, proc{|l,m| "Irbsh.enable_dryrun;#{m.pre_match}\n" }], [ /^ /, proc{|l,m| "irbsh_system %Q(#{l.chomp})\n" }], [/^defun +(\S+)\s*\(([^\)]*)\)/, proc{|l,m| %Q!self.class.__send__(:define_method,:#{m[1]}) do |#{m[2]}|#{m.post_match}! }], [ /^([a-z][a-zA-z0-9]*)\s+\(([^\)]*)\)/, proc{|l,m| %Q!self.class.__send__(:define_method,:#{m[1]}) do |#{m[2]}|#{m.post_match.chomp} end\n! }], ] # @pre: l[-1,1] == "\n" def self.input_filter(l) raise Exception unless "\n" == l[-1,1] begin match = nil x = FILTERS_DEFAULT.find{|re, str| match = l.match(re)}[1] rescue return l end s = x.call(l,match) $debugout.puts "input_filter:#{s}" s end end end class RubyLex alias :set_input_original :set_input def set_input(*args,&block) set_input_original(*args,&block) input_original = @input @input = lambda{ l = input_original.call if self.indent == 0 && l.respond_to?(:replace) l.replace(IRB::InputFilter.input_filter(l)) end l } end end module IRB NULLPROC = lambda{} IRB.conf[:PRE_PROC]=NULLPROC IRB.conf[:POST_PROC]=NULLPROC IrbOriginal = Irb remove_const :Irb class Irb < IrbOriginal def prompt(prompt, ltype, indent, line_no) if prompt==@context.prompt_i && indent == 0 super else "" end end end ContextOriginal = Context remove_const :Context class Context < ContextOriginal def evaluate(line, lineno) line.replace "IRB.conf[:POST_PROC].call; IRB.conf[:PRE_PROC].call; #{line}" super end end end > これなのですが,Rubyのドキュメントを読む限りメソッド名で?を特別扱いすると > いう記述はないようなのですが,どのあたりに書いてある話でしょう? んー。どのみちエラーですね。 irbsh[30@06:23](main):003:0> def ?a(x) 1 end SyntaxError: compile error (irbsh):3: syntax error, unexpected tINTEGER IRB.conf[:POST_PROC].call; IRB.conf[:PRE_PROC].call; def ?a(x) 1 end ^ from (irbsh):3 from :0 irbsh[30@14:28](main):004:0> def a?a(x) 1 end SyntaxError: compile error (irbsh):4: syntax error, unexpected '(', expecting '\n' or ';' IRB.conf[:POST_PROC].call; IRB.conf[:PRE_PROC].call; def a?a(x) 1 end ^ from (irbsh):4 from :0 irbsh[30@14:29](main):005:0> def a?(x) 1 end nil > そうですね.でもメソッドチェインで補完しながら調べられる今の方法も > 捨てがたいんです. というわけで preprocessor 案をお試しください。 -- rubikitch http://www.rubyist.net/~rubikitch/