On May 28, 2011, at 2:05 PM, Christopher Dicely wrote:
> 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 == 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 == 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