永井@知能.九工大です.
<=> オペレータは -1, 0, 1 を返しますが,
ruby ではいずれの場合も論理評価すると true なのですよね?
ですが,== の場合は偽として評価してもらいたいと思ったことはないでしょうか?
例えば,メンバ mem_a, mem_b を持つある構造体クラスがあって,
その大小比較を定義したいというような場合です.
メンバのオブジェクト間の <=> は定義されているとして,
mem_a を高い優先順位として比較しようとすると,
-----------------------------------
def struct_cmp (a, b)
c = a.mem_a <=> b.mem_a
if (c == 0)
a.mem_b <=> b.mem_b
else
c
end
end
-----------------------------------
などとすることになるでしょう.
ですが,ここでもし == の場合には false を返すような比較オペレータ <> が
存在したとすると,例えば
-----------------------------------
def struct_cmp (a, b)
(a.mem_a <> a.mem_a) || (a.mem_b <=> a.mem_b)
end
-----------------------------------
でよいということになります.
よけいな変数も不要ですし,すっきり書けるように私には思えます.
で,試しに ruby-1.1b9_06 に <> オペレータを追加する patch を作ってみました.
いかがでしょうか?
--
永井 秀利 (九工大 知能情報)
nagai / ai.kyutech.ac.jp
-----------------ここから---------------------------------
--- compar.c~ Fri Jan 16 21:35:43 1998
+++ compar.c Wed Apr 1 13:51:38 1998
@@ -17,6 +17,17 @@
static ID cmp;
static VALUE
+cmp_necmp(x, y)
+ VALUE x, y;
+{
+ VALUE c = rb_funcall(x, cmp, 1, y);
+ int t = NUM2INT(c);
+
+ if (t == 0) return FALSE;
+ return c;
+}
+
+static VALUE
cmp_eq(x, y)
VALUE x, y;
{
@@ -89,6 +100,7 @@
Init_Comparable()
{
mComparable = rb_define_module("Comparable");
+ rb_define_method(mComparable, "<>", cmp_necmp, 1);
rb_define_method(mComparable, "==", cmp_eq, 1);
rb_define_method(mComparable, ">", cmp_gt, 1);
rb_define_method(mComparable, ">=", cmp_ge, 1);
--- parse.y~ Wed Mar 25 18:39:37 1998
+++ parse.y Wed Apr 1 13:49:47 1998
@@ -188,9 +188,10 @@
%token UMINUS /* unary- */
%token POW /* ** */
%token CMP /* <=> */
+%token NECMP /* <> */
%token EQ /* == */
%token EQQ /* === */
-%token NEQ /* != <> */
+%token NEQ /* != */
%token GEQ /* >= */
%token LEQ /* <= */
%token ANDOP OROP /* && and || */
@@ -222,7 +223,7 @@
%nonassoc DOT2 DOT3
%left OROP
%left ANDOP
-%nonassoc CMP EQ EQQ NEQ MATCH NMATCH
+%nonassoc CMP NECMP EQ EQQ NEQ MATCH NMATCH
%left '>' GEQ '<' LEQ
%left '|' '^'
%left '&'
@@ -514,6 +515,7 @@
| '^' { $$ = '^'; }
| '&' { $$ = '&'; }
| CMP { $$ = CMP; }
+ | NECMP { $$ = NECMP; }
| EQ { $$ = EQ; }
| EQQ { $$ = EQQ; }
| MATCH { $$ = MATCH; }
@@ -655,6 +657,10 @@
{
$$ = call_op($1, CMP, 1, $3);
}
+ | arg NECMP arg
+ {
+ $$ = call_op($1, NECMP, 1, $3);
+ }
| arg '>' arg
{
$$ = call_op($1, '>', 1, $3);
@@ -2372,6 +2378,11 @@
pushback(c);
return LEQ;
}
+ if (c == '>') {
+ return NECMP;
+ pushback(c);
+ return '<';
+ }
if (c == '<') {
if (nextc() == '=') {
yylval.id = LSHFT;
@@ -3915,6 +3926,7 @@
'^', "^",
'&', "&",
CMP, "<=>",
+ NECMP, "<>",
'>', ">",
GEQ, ">=",
'<', "<",