From: keiju@... (=?ISO-2022-JP?B?GyRCQFBETTc9PHkbKEI=?= ) Date: 1997-06-13T22:02:02+09:00 Subject: [ruby-list:3119] Re: [Q] singleton method for module けいじゅ@今はフリー(^^;;;です. In [ruby-list :03116 ] the message: "[ruby-list:3116] Re: [Q] singleton method for module ", on Jun/13 14:43(+0200) matz@caelum.co.jp (Yukihiro Matsumoto) writes: >深いかどうかは分かりませんが,以下のような理由です > > クラスの特異メソッドがサブクラスに継承される理由 > > サブクラスはクラスの特殊化したものであり,特異メソッドも > 引き継ぐべきだから > > モジュールの特異メソッドがクラスに追加されない理由 > > モジュールのインクルードはモジュールの定義している定数と > メソッドをクラスに導入するもので,クラスがモジュールの特 > 殊化したものになるわけではないから > >どうでしょう? なるほど... といいたいところですが... In [ruby-list :03117 ] the message: "[ruby-list:3117] Re: [Q] singleton method for module ", on Jun/13 14:54(+0200) matz@caelum.co.jp (Yukihiro Matsumoto) writes: >ごめん,で本当はなにがやりたいのか良く分かりませんでした. > > module Foo > class C1 > end > end > > class Bar > include Foo > end > > class Baz > include Foo > end > >とは違うみたいだし.次の例はもっと分からなかった.selfに >splitするとなにが起こるんでしょう? self.to_sでした. それはよいとして, 以下のようなモジュールを考えていました. 返事が来るまでに大体解決はした のですが... module Exception2MessageMapper # E2MM_ErrorMSG: Exception -> Message(printf form) E2MM_ErrorMSG = Hash.new # def_exception(c, m) # c: exception_name # m: message_form # 例外名``c''をもつ例外を定義し, そのメッセージをmとする. # def Exception2MessageMapper.def_e2message(c, m) E2MM_ErrorMSG[c] = m end # def_exception(c, m) # c: exception_name # m: message_form # 例外名``c''をもつ例外を定義し, そのメッセージをmとする. # def Exception2MessageMapper.def_exception(c, m) eval "class #{c} < Exception end print #{c}, '\n' E2MM_ErrorMSG[#{c}] = '#{m}'" end private :def_exception def fail!(*opt) super end # fail(err, *rest) # err: 例外 # rest: メッセージに渡すパラメータ # def fail(err, *rest) super(err, sprintf(E2MM_ErrorMSG[err], *rest)) end end つまり, 例外の定義とそのメッセージへのマッピングを定義するモジュールで す. それで, 以下のように, Matrix, Vectorの例外を定義します. module ExceptionForMatrix include Exception2MessageMapper # Exception def_e2message(TypeError, "wrong argument type %s (expected %s)") def_e2message(ArgumentError, "Wrong # of arguments(%d for %d)") def_exception("ErrDimensionMismatch", "\#{self.class} dimemsion mismatch", binding) def_exception("ErrNotRegular", "Not Regular Matrix", binding) def_exception("ErrOperationNotDefined", "This operation(%s) can\\'t defined", binding) end で使い方は class Matrix include ExceptionForMatrix ... def inverse ... fail ErrNotRegular ... end end class Vector include ExceptionForMatrix ... end 今な感じにしたかったのでした. でも問題が幾つかありまして... 1. ExceptionForMatrixから def_exceptionが呼び出せない. クラスを直接指 定する必要があるのでちょっと気分が悪い. 2. def_exception内でevalするため, そこで定義される例外が Exception2MessageMapperローカルになる. ExceptionForMatrixローカルな 例外としたい. 3. さらに, よく見ると E2MM_ErrorMSGもException2MessageMapperローカルと なっていて, ExceptionForMatrixローカルになっていない. で, これを解決するために. 1. includeでなくてクラスに直接extendする. 2. ExceptionForMatrixのバインディングをクラスのインスタンス変数に保存 し, evalはそのバインディングを用いて行う. として, こんなコードにしてみました. def toplevel_binding binding end module Exception2MessageMapper RCS_ID='-$Header: $-' def Exception2MessageMapper.extend_to(cl) case cl when Class cl.extend(self) eval "class #{cl} #{cl}.bind(binding) end", toplevel_binding when Module cl.extend(self) eval "module #{cl} #{cl}.bind(binding) end", toplevel_binding else fail ErrNotClassOrModule end end def bind(b) # E2MM_ErrorMSG: Exception -> Message(printf form) @binding = b eval "E2MM_ErrorMSG = Hash.new def fail! super end def fail(err, *rest) # $@ = caller(1) super(err, sprintf(E2MM_ErrorMSG[err], *rest)) end public :fail ", @binding end # def_exception(c, m) # c: exception_name # m: message_form # 例外名``c''をもつ例外を定義し, そのメッセージをmとする. # def def_e2message(c, m) eval "E2MM_ErrorMSG[#{c}] = '#{m}'", @binding end # def_exception(c, m) # c: exception_name # m: message_form # 例外名``c''をもつ例外を定義し, そのメッセージをmとする. # def def_exception(c, m) eval "class #{c} < Exception end print self.inspect, '\n' print #{c}, '\n' E2MM_ErrorMSG[#{c}] = '#{m}'", @binding end def fail!(*opt) super end Exception2MessageMapper.extend_to(self) def_exception("ErrNotClassOrModule", "Not Class or Module") end module ExceptionForMatrix Exception2MessageMapper.extend_to(self) def_e2message(TypeError, "wrong argument type %s (expected %s)") def_e2message(ArgumentError, "Wrong # of arguments(%d for %d)") def_exception("ErrDimensionMismatch", "\#{self.class} dimemsion mismatch") def_exception("ErrNotRegular", "Not Regular Matrix") def_exception("ErrOperationNotDefined", "This operation(%s) can\\'t defined") end これで問題ないですよね?? ところでバグを幾つか発見しました. 1. 1.extend(aModule) ../e2mmap.rb:21: [BUG] Segmentation fault IOT trap 2. eval "print 1", TOPLEVEL_BINDING ../e2mmap.rb:24: [BUG] Segmentation fault IOT trap __ .........................................石塚 圭樹@今はフリー(^^;;... ------->>また, アドレス変わりました!! e-mail: keiju@bc.mbn.or.jp <<---