From: keiju@... (Keiju ISHITSUKA) Date: 1998-04-03T11:27:32+09:00 Subject: [ruby-dev:2035] Re: coerce けいじゅ@日本ラショナルソフトウェアです. In [ruby-dev :2005 ] the message: "[ruby-dev:2005] Re: coerce ", on Mar/31 19:21(JST) Toyofuku writes: > 豊福@パパイヤです。 >> 1. alias名の管理が面倒 >> 2. へんなaliasがNumericの下にいっぱいできてしまう. >> ということで, 私はあまり推薦できません. > > alias の問題は私も coerce や modulo のプログラムで >演算の再定義を書いていて感じました。それで、 >・上の例でいえば old_mul という名前が(C言語の static > 関数みたいな感じで)外から見えないようにならないか。 これは, privateを使えばできますね. >・hook みたいな仕掛けで本来の * が呼ばれる前に新規追加 > 部の * が呼ばれるようにできないか。 rubyに標準の機能としてですか? なかなか難しいんじゃないですかね... 以下のような感じでモジュールを定義することはできますけど... aliasを自動的に定義し, 新定義の方で例外が発生したらaliasの方を呼ぶよう にしています. ただ, 定義を文字列で渡さなくてはいけないので, そこが問題 ですね... イテレータを使えば def_extention("foo", arg) do def foo ... end end のような感じにできるんですけど, 余分なメソッドがさらに1つ増えるのが... -- "extention.rb" -- module ExtentionMethod @RCS_ID='-$Id: $-' class << self attr :pre, true attr :post, true end @pre = "__aliased__" @post = "__" def def_extention(method, arg, body) base = ExtentionMethod.pre + method.intern + ExtentionMethod.post ali = base no = 0 while instance_methods.include?(ali) no += 1 ali = base + no end module_eval "alias #{ali} #{method} def #{method}(#{arg}) begin #{body} rescue return #{ali}(#{arg}) end end " end end irb:001:0> load "extention.rb" true irb:002:0> class Foo irb:003:1> extend ExtentionMethod irb:004:1> def foo(t) irb:005:2> print "foo\n" irb:006:2> end irb:007:1> end nil irb:008:0> class Foo irb:009:1> def_extention("foo", "t", "if t then fail 'exp' else print 'new foo\n' end") irb:010:1> end nil irb:011:0> f = Foo.new # irb:012:0> f.foo(false) new foo nil irb:013:0> f.foo(true) foo nil irb:014:0> Foo.methods irb:015:0> Foo.instance_methods ["__aliased__10817__", "foo"] irb:016:0> class Foo irb:017:1> def_extention("foo", "t", "if t==0 then print 'new new foo\n' else fail 'exp' end") irb:018:1> end nil irb:019:0> Foo.instance_methods ["__aliased__10817__", "foo", "__aliased__10817__1"] irb:020:0> f.foo(0) new new foo nil irb:021:0> f.foo(false) new foo nil irb:022:0> f.foo(true) foo nil irb:023:0> > 確かにそうですね。ただ Scalar の件では Numeric という >名前を Scalar に代えただけで実質 Numeric で処理している >ような気がしてそれなら直接 Numeric に定義した方が素直で >はないかと思ったんです。 そうかも知れませんね(^^;;; > それとオブジェクト指向というとレシーバができるだけ頑 >張って処理するというイメージがあって Numeric側で頑張った >方がオブジェクト指向っぽいかなという思いもありました。 これは... この場合はメッセージ指向のオブジェクト指向の悪い点が出ている 例ですかね(^^;;; 普通は, receiver.method(...) では, レシーバが頑張るものなのですが, 2項演算子の場合は, 右辺と左辺に 対象性があるのでどっちが頑張るというものでもないですしね. >> ほしいですねえ... >> でも, rubyでやるのは重いかなって気もするし... > > 気がします。でも私はガンガン使うことはないだろうから >遅いのでもいいから欲しいです。 それもいえますね(^^;; >本格的に使いたくなったらC言語で拡張モジュール書いてもらって。 (^^;;; PS. 何か話しがそれてきたなあ... __ ................................石塚 圭樹@日本ラショナルソフトェア... ----------------------------------->> e-mail: keiju@rational.com <<---