Infrequent Update

Monday, May 01, 2017

Common misconceptions about immediate values in Ruby

Immediate Values

Frequently you can read in Ruby discussions sentences like "You cannot do X because Y is an immediate value". Or: "You must (not) use immediate values for Z."

If you do not know what immediate values are, here is the brief explanation: immediate values in Ruby are an implementation of tagged pointers. This means, that pointers for all Fixnum values, true, false and nil do not point to objects on the heap but are self contained. This is an internal optimization of MRI which saves memory and speeds up certain math operations because they do not require memory allocation (and thus no bookkeeping for GC and, of course, no GC either).

Now I told you too much already, because for programming Ruby this is - irrelevant. Of course, there are the optimization effects mentioned above, but beyond that immediate values have no effect on how you write your Ruby programs. Heck, you cannot even notice whether something is an immediate value or not in a Ruby program!

Now, some of you might say, "Wait, there are certain things I cannot do with immediate values, i.e. I cannot change them!". Well, that is true (except for when it was possible to add instance variables to Fixnums, e.g. in 1.8.7) but there are more immutable objects around, namely Symbol and every object that you have frozen. The important distinction is between "mutable" and "immutable" objects, not between "immediate values" and "regular objects" because only this is noticeable and has effects on a programs working.

If you do not believe this you can try to write a function is_immediate(obj) in Ruby which returns a trueish value iff obj is an immediate value without resorting to your knowledge about which types have immediate values. You can also think about what lines of code you would have to change in your Ruby programs if Matz decides tomorrow to put all Fixnums on the heap.

Where it came from

I assume that since Fixnums, true, false and nil are immediate values and immutable people tend to assume that the immutability is somehow closely tied to immediate values. And it is reasonable to expect immediate values to be immutable because there is no place in memory to store state (at some point in time I need to dig into how it was done in 1.8.7).

But: objects can be immutable without being immediate values, this is not a requirement. Any object that does not have state modifying methods is immutable. It can have as much state as it likes to have as long no client can change it.

Ruby's math operators like +, -, * and / work in a way that you must keep the return value because most often you get a reference to another object back. Some people might be led to believe that in Ruby there is inplace modification of math values because there is operator +=. But x += 2 is really only syntactic sugar for x = x + 2. (Note that this was a very wise decision of Matz because that allows a seamless transition between numeric types; if you keep multiplying a Fixnum value by two you will inevitable get a Bignum at some point in time.)

Conclusion

Yes, there are immediate values in MRI. No, they do not have effects on the logic and functionality of your program, they are indistinguishable from other object references. They still do have their value (pun intended) but when reasoning about why a particular program needs to be or can be written in a certain way, think about mutability vs. immutability - not some arcane optimization of the interpreter.

Labels: , ,

1 Comments:

Post a Comment

<< Home