In article <1053418411.495451.20782.nullmailer / picachu.netlab.jp>,
  matz / ruby-lang.org (Yukihiro Matsumoto) writes:

> 要するに
>
>   * <=>が成立しないケースは厳密には2種類ある
>     + そもそも型が合わない
>     + 型は合うが順序関係が成立しない
>   * これらを区別するため、前者は例外、後者はnilになるべきだ。
>
> ということですよね。

はい。

> 私の考えとしては
>
>   * 2種類を区別する必要があるのか
>
>     ほとんどの場合、ユーザが関心あるのは、比較できるかできな
>     いかだけ。

同意できません。ほとんどの場合、ユーザは比較できるときのことしか関心を
持たないように思います。

したがって、比較できないときに対処するコードが少なくなるような仕様が良
いと思います。

>     「情報は多い方が良い」とは限らない。むしろ場合分けが多く
>     なるかも。

反論します。普通のプログラムではこの例外はバグを示すため、rescue する
必要はありません。つまり、場合分けは多くなりません。

そして、例外は nil よりもバグを早期に検出します。nil を返した場合には
問題を検出するにはユーザが自分で検査しなければいけませんが、例外ならな
にも書かないで検出されます。

もちろん、多くの場合、正しいプログラムは比較できないものを比較したりは
しないので、これはユーザがバグを追いかけているといった状況の話です。

例外にしておけば、なにもしなくても検査が入っている状況になり、ユーザは
無用にプログラムを疑わなくて済みます。

まぁ、<=> を直接使うのは主に sort のブロックで、その場合は nil を返せ
ば例外になるから、この理由はちょっと弱いかもしれませんが。

>     半順序関係はクラス/モジュールだけだし、理由はともかく順
>     序関係が成立しないのだから、差別する必要はない。

反論します。この情報の欠落は反対称律の実現を厄介にします。

% ruby -rdelegate -e '
class C; end
class D; end
c = SimpleDelegator.new(C)
p c < D
p D < c
'
nil
-e:6:in `<': compared with non class/module (TypeError)
        from -e:6

例外を出すべきかどうかという条件判断を <=> がしてくれないため、その判
断を <, <=, >, >= に埋め込む必要があります。そして、<, <=, >, >= を
<=> の呼び出しによって実現するのであれば、比較可能なクラスは相互に相手
を知っていなければなりません。その結果、比較可能な後からクラスが増える
状況を扱うのが困難になります。

もちろん、組み込みの中で半順序なのは Module だけで、Module と比較可能
なクラスを後から付け加えるというのは非現実的ですが、<=> というメソッド
の使いかたの範を示すという意味でよろしくないと思います。

>   * ないとすると、成立しない場合には、例外かnilか
>
>     例外だとエラーメッセージに内部利用されている<=>が登場す
>     ることになる

これはまったく考えていませんでした。なるほど。

>     これを避けるにはコストのかかる例外補足が必要
>
>     => nilの方が良い
>
> ということで、現状維持を推します。
>
> nilから適切なメッセージを持つ例外に変換する方が、例外を補足
> して適切なメッセージで再発生させるのより安いというのも動機の
> 一つです。

効率に関しては反論しません。

たしかに、上で述べたような利点を実現するのに引き合うかどうか、というバ
ランスを考慮する必要はあると思います。
-- 
[田中 哲][たなか あきら][Tanaka Akira]