I understand that using String#replace works for the String class, but=20=
what if you were writing a random method for Integer that takes a = number=20
and sets it equal to some other number.
=20
Ex.
=20
x =3D 7
=20
class Integer
def crazy
...set x to 5...
end
end
=20
=20
now when you call x the value is 5
This seems like a simple question but it touches on some very deep =
issues of Ruby's object model. Understanding the object model is the =
key to understanding why your question doesn't make sense in Ruby.
Ruby's fixnum objects are not containers for an integer value. This =
means that for any particular fixnum object there is no way to alter it =
so that it no longer behaves like a 7 and instead behaves like a 5, for =
example. The integer semantics of a fixnum object are defined by the =
object's *identity*, not by any state it carries around (i.e. instance =
variables or state that is hidden from the programmer but maintained by =
the runtime).
In that example you can see that y and z reference the *same* object, =
which happens to be object 15 in my version of Ruby and which happens to =
behave like the integer 7. The Ruby runtime ensures that object 15 =
always behaves like the integer 7 and that it is the *only* object that =
behaves like the integer 7.
And yes, you can attach instance variables to fixnum objects:
So you can see that within Ruby's object model there is one and only one =
fixnum object that behaves like the integer 2. That particular object =
in MRI Ruby 1.9.2 happens to have an object_id of 5, but that is really =
just an implementation detail.=20
Lots and lots of Rubyists describe fixnum objects as 'immutable', but as =
shown above with instance variables, that is simply not an accurate =
description of Ruby's fixnum objects. The characteristic that =
erroneously gets labeled as 'immutability' is that the semantics of a =
fixnum object are defined by its *identity* and not by its state. A =
consequence of this property is that having a *reference* to a fixnum is =
all you need to interact with the object. The underlying object doesn't =
even have to 'exist' within the runtime (i.e. there is no memory =
allocated for every fixnum object). The runtime can emulate the =
behavior of fixnum objects simply by manipulating the *references* =
without ever instantiating the objects. See =
<
http://en.wikipedia.org/wiki/Tagged_pointer> for more about how this =
sort of thing is implemented. There are several other Ruby classes that =
have this behavior and tend to be implemented in this way: nil, true, =
false from NilClass, TrueClass, and FalseClass respectively and symbols.
Going back to your original question about setting x to a new value. =
Another way of interpreting that request is not that you are mutating =
the object that x references but instead you are rebinding the variable =
x to a different object. Ruby variables are simply named containers for =
object references so if you can replace the reference to the fixnum 7 =
associated with variable x with a reference to the fixnum 5, you will =
have 'set x to 5', which is exactly what Ruby's assignment operation =
does.
There are a variety of ways for a Ruby method to gain access to variable =
bindings that are out of the direct scope of the method but it is =
generally considered bad form for a method to alter variable bindings =
outside its scope. Nevertheless, here is one way to do it:
class Integer
def assign(name, value, binding_object)
eval "#{name} =3D #{value}", binding_object
end
end
This sort of use of eval and binding is *not* at all common and probably =
only comes into play with various debugging or programming tools rather =
than in the normal course of writing Ruby programs.
Gary Wright