itsme213 wrote:

> You can try to work the angle that value-like things (Fixnums) are
> fundamentally different from objects, but I think there is a simpler
> explanation. Along the general lines some others have said in this thread,
> but with some differences.

Fixnums are Objects, even if they are not represented by an actual 
Object structure in Ruby. You can do method calls on them, access their 
instance variables etc.

> A variable always 'holds' ('contains', 'its value is') a _reference_ to an
> object.  This is true for local variables, instance variables, encoded
> instance variables (see below), integer-indexed variables array members,
> key-indexed variabels like hash entries, global variables. In fact, it is
> even true for Constants; I like to think of all of these as 'slots'; some
> slots may be 'frozen', ... i.e. they can never refer to a different object
> (see below).

I'd just say that Objects are in most cases represented by VALUEs. I'm 
not sure what you mean with "encoded instance variables".

> Most references are encoded as in-memory pointers to heap-allocated storage
> corresponding to that object. That heap allocated storage, in turn, contains
> a its own 'variables' (called instance variables), which also always 'hold'
> references to objects. Methods on these objects can refer to their instance
> variables (and to methd args, and to globals and constants).

It does not only contain instance variables. There's also information 
like klass, flags, string buffer pointers and more in the internal 
Structs. (And not all Objects store their instance variables in those 
internal Structs, see exivars.)

> Fixnums are encoded as 2's complement bit strings (for example).
>     Thus, '0000' is an encoded _reference_ to the fixnum '0'.
>     And '0001' is an encoded _reference_ to the fixnum '1'.

I don't quite get this. How is '0000' different from '0' and '0001' from 
'1'? If you're talking about object ids you should have used  object_id 
= 1 + (fixnum << 1). (just prepend a '1' in binary representation.)

> Such encodings also encode a set of 'instance variables' that those objects
> would have explicitly stored had they been represented on the heap like
> normal objects. For example, the encoding of Fixnum '1' implicitly encodes
> references to its adjacent fixnums '0' and '2'.  The number '0' existed well
> before the bit pattern '0001' ever appeared in your Ruby program.

I'm not sure if you're using an analogy there, but Fixnums certainly 
don't store their neighbors at all. It's a well-known fact that 2+1 == 
3, you don't need to store that in an instance variable.

> Of course, methods on such objects need access to these 'instance
> variables', so the methods are also optimized so they can simply work with
> the encoded reference (rather than with the object itself), and again
> guarantee to return (possibly encoded) references to objects.

Methods take Objects and return Objects. They don't care if that Object 
is encoded in a VALUE or actually backed up by an actual Object struct.

> The discussion of Fixnums are 'immutable' is right in spirit, but in detail
> bears closer inspection. Certain 'encoded' instance variables of Fixnums are
> frozen. Specifically, their relationships to all other fixnums dictated by
> the laws of math. i.e. these encoded instance variables are automaticaly
> 'frozen' (there was a long earlier thread on this topic). After all, you
> would not want 2+1 to change from 3 to 73 in the middle of your program.

Again, not sure if this is supposed to be an analogy or simplistic view 
of things, but the result of 2+1 is certainly not dictated by instance 
variables and there are no 'special frozen instance variables' in Ruby. 
And 2+1 can be changed from 3 to 73. After all 2+1 is just calling the 
plus method on 2 with the argument 1. And methods can be changed:

class Fixnum
   alias :old_plus :+

   def +(other)
     return 73 if self == 2 and other == 1

     old_plus(other)
   end
end

> However, Fixnums can certainly have other mutable 'instance variables'; we
> just have to handle the internal implementation differently because the
> objects themselves are not heap allocated, so we need some other means to
> get to these 'inst-vars'.
> class Fixnum
>     @@foos = {}
>     def foo; return @@foos[self]; end
>     def foo=(x); @@foos[self]=x; end
> end

This are no instance variables, this are class variables.

Why don't just use instance variables directly? (After all Fixnums can 
have instance variables. They are not stored in the Object struct of 
Fixnums, of course, as Fixnums have no Object structs. So where do they 
go? There's a global exivar table for Objects that can not store their 
instance variables in Object structs. They go there. You don't notice 
this, of course, and that's a good thing.)

> irb(main):001:0> 1.instance_variable_set("@chosen_one", true)
> => true                                                     
> irb(main):002:0> 1.instance_variable_get("@chosen_one")     
> => true                                                     
> irb(main):003:0> 2.instance_variable_get("@chosen_one")     
> => nil