Hi,

2009/7/11 Run Paint Run Run <redmine / ruby-lang.org>:
> Defining instance methods on Fixnum instances seems a particularly contri=
ved case, even for ruby-core. ;-)

Please don't count on me so much ;-)


> Triskadekaphobiacs are presumably upset that, although 13.untrust appears=
 to succeed and reinforce their beliefs, the state doesn't stick; 13.untrus=
ted? subsequently returns false. Similarly, logicians and cynics alike must=
, respectively, rejoice and despair that `true.untrust.untrusted?` is perpe=
tually false.

Whoa!  The current behavior of 1.9 is never reasonable.
Here is a patch:


Index: object.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- object.c	(revision 24034)
+++ object.c	(working copy)
@@ -641,6 +641,8 @@
     return Qnil;
 }

+static st_table *immediate_tainted_tbl =3D 0;
+
 /*
  *  call-seq:
  *     obj.tainted?    =3D> true or false
@@ -653,6 +655,10 @@
 {
     if (OBJ_TAINTED(obj))
 	return Qtrue;
+    if (SPECIAL_CONST_P(obj)) {
+	if (!immediate_tainted_tbl) return Qfalse;
+	if (st_lookup(immediate_tainted_tbl, obj, 0)) return Qtrue;
+    }
     return Qfalse;
 }

@@ -674,6 +680,12 @@
 	    rb_error_frozen("object");
 	}
 	OBJ_TAINT(obj);
+	if (SPECIAL_CONST_P(obj)) {
+	    if (!immediate_tainted_tbl) {
+		immediate_tainted_tbl =3D st_init_numtable();
+	    }
+	    st_insert(immediate_tainted_tbl, obj, (st_data_t)Qtrue);
+	}
     }
     return obj;
 }
@@ -696,9 +708,14 @@
 	}
 	FL_UNSET(obj, FL_TAINT);
     }
+    if (SPECIAL_CONST_P(obj) && immediate_tainted_tbl) {
+	st_delete(immediate_tainted_tbl, &obj, NULL);
+    }
     return obj;
 }

+static st_table *immediate_untrusted_tbl =3D 0;
+
 /*
  *  call-seq:
  *     obj.untrusted?    =3D> true or false
@@ -711,6 +728,10 @@
 {
     if (OBJ_UNTRUSTED(obj))
 	return Qtrue;
+    if (SPECIAL_CONST_P(obj)) {
+	if (!immediate_untrusted_tbl) return Qfalse;
+	if (st_lookup(immediate_untrusted_tbl, obj, 0)) return Qtrue;
+    }
     return Qfalse;
 }

@@ -730,6 +751,12 @@
 	    rb_error_frozen("object");
 	}
 	OBJ_UNTRUST(obj);
+	if (SPECIAL_CONST_P(obj)) {
+	    if (!immediate_untrusted_tbl) {
+		immediate_untrusted_tbl =3D st_init_numtable();
+	    }
+	    st_insert(immediate_untrusted_tbl, obj, (st_data_t)Qtrue);
+	}
     }
     return obj;
 }
@@ -752,6 +779,9 @@
 	}
 	FL_UNSET(obj, FL_UNTRUSTED);
     }
+    if (SPECIAL_CONST_P(obj) && immediate_untrusted_tbl) {
+	st_delete(immediate_untrusted_tbl, &obj, NULL);
+    }
     return obj;
 }



Maybe it is best to freeze all immediates (+ bignum) by default.
If Gary's example is needed at any cost, it can probably be rewrited
without using instance variables.


  class Fixnum
    h =3D {}
    define_method(:note=3D) {|x| h[self] =3D x }
    define_method(:note) { h[self] }
  end

  42.note =3D "the answer"
  p 42.note


At any rate, I think that this is a talk about the future, perhaps
after Ruby 2.0.

--=20
Yusuke ENDOH <mame / tsg.ne.jp>