From: keiju@... (=?ISO-2022-JP?B?GyRCQFBETTc9PHkbKEI=?= ) Date: 1998-02-24T15:47:46+09:00 Subject: [ruby-list:6707] Re: coerce けいじゅ@日本ラショナルソフトウェアです. In [ruby-list :06704 ] the message: "[ruby-list:6704] Re: coerce ", on Feb/24 14:59(JST) Yukihiro Matsumoto writes: >まつもと ゆきひろです >| coerce って二項演算のときに使われるのが主な >|目的だと思っているのですが演算についての情報 >|がなくてもよいのですか。 > >coerceの目的は「俺はお前に対してどう演算して良いのか分からん. >俺をお前の知っている型に変換してくれ」というものです.んで, >変換された型がそれぞれの演算を行うわけです. > >| 例えば obj1 + obj2 と obj1 ** obj2 とでは >|obj2 は異なるタイブや値に変換された方がよい >|こともありそうな気がするのですが。 >そういう場合は相手を知っているのではないでしょうか. ちょっと甘いですね(^^;;; 知っている時はいいのですが, 知らない時はやは り問題になります. ># 本当に大丈夫かどうかは数値に強い人に任せよう. 数値には強くないのですが, 経験者ということで. 確かに, obj1 + obj2 と obj1 ** obj2 が違う型に変換したいことはあるかも 知れません. obj1のクラスをC1, obj2のくらすをC2とします. C1が新規型の場合は問題ないですね. C1#+, C1#** の側で対処すれば良いので すから, 問題はC1がIntegerなどの既存型の場合です. その場合は, エレガントな解決ではないのですが, 以下のようにしますと大体 うまくいくと思います. まず, 新しい型C3をつくります. class C3 def initialize(val) @value = val end end つぎに, C2#coerce(other)では def coerce(other) C3.new(other), self end のように, otherをC3に変換します. 次に, class C3 def + (other) @value + otherを適当な型に end def **(other) @value ** otherを適当な型に end end と適当な演算を定義します. 間接的なクラスを導入するところが味噌ですね. matrix.rbの中で, 同じような技法を使っています. Matrix Matrix::Scalar Vector でMatrix::Scalarは上記C3に相当していてNumericをラップするクラスになっ ています. この場合は上記のような要望というわけでもないんですが, 近いと いえば近い理由からでした. n * M を計算するのに, Matrix#coerce(num) で変換しようがなかったからです n * M の時は, nを nI に変換すれば良いのですが, その変換では n + M で困 ります(エラーにしたい). そこで, coerceでは Scalar.new(num), self を返して, Scalar::*(other)で実際の計算を行なわせています. Scalar::+(other)ではエラー. PS. 実は, 私もMatrixを作りはじめた時に, rubyのcoerceでは駄目かと思ったんで す... でも, その時, 松本氏もこの解決案を出したと思いましたが... 私はもっ とエレガントな方法が良かったんですが... __ ................................石塚 圭樹@日本ラショナルソフトェア... ----------------------------------->> e-mail: keiju@rational.com <<---