Method that mutates object

C

Christopher Dicely

This seems like a simple question but it touches on some very deep issues=
of Ruby's object model. =C2=A0Understanding 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. =C2=A0This=
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 examp=
le. =C2=A0The integer semantics of a fixnum object are defined by the objec=
t'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)=
 
G

Gary Wright

That's actually probably not the best description. While its true that
the implementation of the immutability of the arithmetic value of a
Fixnum is implemented (in most and possibly all Ruby implementations)
through a fixed relationship of that value on the identity of the
Fixnum, its worth noting that the value of a Bignum in an arithmetic
context is likewise not dependent on its state, even though Bignums --
unlike Fixnums -- are generally not implemented with a fixed
relationship between value and identity, such that there can be more
than one Bignum object with the same value.

My main point was that 'immutable' is the wrong term to apply to
fixnum objects (and all other objects) in Ruby. You can add instance
variables to anything.

The original poster asked how to change a fixnum representing the
integer 7 to a fixnum representing the integer 5, which you can't
do because fixnum semantics are based on identity, not state.

You are correct that in the bignum case you also can't mutate a
bignum object so that it behaves like a different integer but for
different implementation reasons. In this case, the integer semantics
of a bignum are carried around in hidden state that is not accessible
to the Ruby programmer. You said that the "value..is not dependent
on its state" but I think you meant that the value is not dependent
on the "visible" state or "programmer accessible" state.

Float is another class that implements its semantics via hidden state.

identity hidden-state hidden-state
semantics semantics accessible?
fixnum yes no no
symbol yes no no
float no yes no
bignum no yes no
string no yes yes (e.g. String#replace)
The real enforcement of the distinction isn't so much that identity
rather than state is used (since this is not true of the
implementation of Bignums) but that you can't define singleton methods
on objects of the built-in numeric types.

I'm not sure what singleton methods have to do with the earlier
discussion. The reason you can't define singleton methods on Fixnum
instances and other core objects is that it would introduce horrible
performance penalties, not that there is something semantically
awkward about it. In fact its absence is what is awkward.
That Fixnums of the same value share object identity is an = implementation detail,
not the fundamental basis of the arithmetic immutability, since the
latter is a feature of Ruby's built-in numerics generally, including
those that don't use Fixnum-style identity-sharing.

The reason that I think the behavior of Fixnum, Symbol, NilClass,
TrueClass, and FalseClass should be understand in the context of
identity semantics is because that property manifests itself in the
way that the equality methods work.

For the 'identity' classes I listed above,
a =3D=3D b if and only if a.equal?(b)

For the other built-in numerics with 'hidden' state that isn't true,
the rule is a bit more relaxed:
a.equal?(b) implies a =3D=3D b (but not the other way around)

There are also performance implications associated with these =
implementation
details. For example symbol equality can be determined by comparing =
references
while string equality cannot.

Gary Wright
 
G

Gary Wright

. . . and I haven't even tried adding an instance variable to that = module
yet. How should I add an instance variable to my fixnum object if not
with extend?

We are talking about two different things. You are talking about =
modifying the singleton class, which you can't do. It is prohibited =
because it would kill performance to dispatch through singleton classes =
for some of the core data types.

But you can manually add instance variables:

3.instance_variable_set("@english", "three")


Or you can modify the Fixnum class:

class Fixnum
attr_accessor :english
end

4.english =3D "four"

In either case you've got fixnum objects with state that can change.

Gary Wright
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,763
Messages
2,569,563
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top