From: NAGAI Hidetoshi Date: 1998-04-02T19:56:24+09:00 Subject: [ruby-dev:2026] Re: [ruby-list:7298] Re: cmp operator 永井@知能.九工大です. # ruby-list からの引っ越しです. # じっくり考えてみていたので遅くなってしまいました. >>>>> "M" == Yukihiro Matsumoto writes: M> In message "[ruby-list:7286] cmp operator" M> on 98/04/01, NAGAI Hidetoshi writes: M> |ですが,ここでもし == の場合には false を返すような比較オペレータ <> が M> |存在したとすると,例えば M> |----------------------------------- M> |def struct_cmp (a, b) M> | (a.mem_a <> a.mem_a) || (a.mem_b <=> a.mem_b) M> |end M> |----------------------------------- M> |でよいということになります. M> |よけいな変数も不要ですし,すっきり書けるように私には思えます. M> |いかがでしょうか? M> うーん,たしかに「この局面に限れば」非常にすっきり書けます. M> 採用したいという誘惑にかられないでもないのですが, M> * 演算子を増やすことによって言語の複雑化を招かないか M> * 他の言語では <> は != と同義のものが多いが,この<>は(似 M> てないでもないが)意味が違う.そのことが正当化されるか M> * どうせ言語に変更を加えるなら,むしろ0も偽とした方がすっ M> きりしないか M> というような思いもあり,素直に採用とは行かないように思います. M> ということで,更なる議論を行いたいのですが,ruby-dev で続き M> をやりません? 確かに演算子を際限なく増やしていくことは問題がありますね. 結局は,演算子が増えたことによる (1)利用者が修得に要する負荷の増加 (2)利用者がプログラム記述に要する負荷の減少 (3)システムにおける字句解析器の負荷の増加 (4)システムにおける演算子処理実現の負荷の増減 という点での費用対効果の問題という理解でよいのでしょうか? まずは「演算子を増やすことによって言語の複雑化を招かないか」 についてです. 最初に上記(1)についてですが,複雑化という側面で見て, 修得に要する負荷の大小は,その機能が容易に類推できるか という点にあると思います. この点については <=> から = を除いたということで イメージしやすいのではないかと思います. 逆に == に対しての <> との理解をしたとしても, 真偽値としては矛盾がありません. 適用可能なのが大小関係を持つものに限ると言う点はありますが, これも大小記号を使っている点からイメージしやすいと思います. (2)については,例で示した通りすっきりと書けるわけですから, ありがたい負担の減少ですよね. 次にシステム面での複雑化の側面ですが, patch を見ていただければわかる通り, この演算子を導入するためのソースの修正はわずかなものです. <=> に基づいて判定するように Comparable モジュールで定義していますので, 同モジュールをインクルードしている(できる)クラスすべてで利用できます. 修正量に対する効果範囲は十分に大きいと思います. (3)についてはわずかなりとも確実に増大しますが, これは内部表現に変換するまでの問題ですよね? (4)については変数を一つ定義する分の負荷が必要なくなります. こちらは実行される度に影響するわけですから, 頻繁に利用されるほど,負荷軽減の効果が大きくなると考えられます. (というように ruby については思っているのですが,ホント?(^_^;) 条件判断ですから,これが欲しくなるような局面があるなら, これはそのプログラム中で頻繁に利用される可能性が高いでしょう. 次に「他の言語では <> は != と同義のものが多いが」という点です. 「正当性」という点では,「そのような意味の演算子が欲しかったから」, そして「意味から考えて <> という記号が最も自然に感じるから」 また「!= との違いも自然にイメージしやすいから」としか言えません. 「他の言語では」というのが問題になるのは, 他の言語の修得者が ruby を学ぶ際に類推するのを裏切らないか ということだと思います. まず,そのような学習者が両者が適用できる範囲において, <> と != とが同じだと考えたとして矛盾が生じるかですが, これは生じないですよね. 一般には != の定義は「両辺に同値関係が成立すれば偽を, 成立しなければ真を返す」ということだと思います. さらに,ここで偽または真を返すというのは, 偽または真と *判定される値* を返すということだと考えます. こう考えた場合,<> と != とは同等に働きます. # <> はついでにどちらが大きいかに応じて正または負の値が # 返ることが保証され,それがありがたいわけですが.(^_^) <> と != との違いは,先にも述べた通り <> : 大小関係が定義されているものに限る != : 同値関係が定義されているものに限る ということであり,大小記号という表現であることから, 大小比較ができるものにしか適用できなくても それを自然なこととして受け入れてもらえそうに思えます. 最後に,「むしろ0も偽とした方がすっきりしないか」という点ですが, 私も最初は「0 は偽としてくれるといいのに」と思いました. しかし,0 を偽と解釈ようにすると,同一クラスのオブジェクトのうちで 一部のものは真であり,一部のものは偽であるという状況が 生じることになります. そうすると,あらゆるクラスにおいて,真値となるオブジェクト, 偽値となるオブジェクトというのを意識しなければならなくなります. これは言語修得者にとってはちょっとした負荷になりますし, システムに取ってはかなり大きな負荷になるのではないでしょうか. 現実として,一部オブジェクトを偽として扱うようにするのであれば, それはシステムの組み込みクラスに限られることになるのでしょうが, それだけとしても「0 が偽なら 0.0 も偽でしょう」とか 「空文字列は偽に」とか「空配列も偽に」とかくらいは 要望が出てくることになると思います. これらのどこまでを認めて,どこからを認めないかを決定する哲学は 結構厄介だろうと考えます. また,サブクラスが絡んでくると問題はさらに複雑化しそうです. オブジェクトにより真偽値が違うクラスのサブクラスを作った場合, そのサブクラスでの真偽値判定はどうなるのでしょうか. これまで判定しなければならないとなると, システム負荷は膨大なものになりそうです. そんなわけで,私には負荷が際限なく膨らんでいきそうに思えたので, 「0 も偽にできないのですか?」ではなく 「<> という演算子はどうでしょう?」という提案となりました. # プログラミング言語のデザインなどはやったことがないですし, # 実はオブジェクト指向言語自体,真面目に触るのは ruby が初めてです. # きちんとした議論になってくれればいいのですが.(^_^; -- 永井 秀利 (九工大 知能情報) nagai@ai.kyutech.ac.jp