Hi –
On Wed, 4 Nov 2009, RichardOnRails wrote:
(b) Dave Black, in his truly excellent “The Well-Grounded Rubyistâ€
def show(v)
“Got #{v}, class = #{v.class}, object_id = #{v.object_id}
(v.object_id-1)/2 = #{(v.object_id-1)/2 }”
end
a = 1; show (a) => Got 1; class = Fixnum; object_id = 3; v >> 1
= 1
b = 1; show (b) => Got 1; class = Fixnum; object_id = 3; v >> 1
= 1
a == b => true
And a.equal?(b) is also true.
Both “a†and “b†have their respective values held as immediate values
(embedded in their object_id’s), but they are NOT the same thing
because they’re ultimately held in their respective entries in the
symbol table.
But the symbol table, which contains :a and :b, is not the arbiter of
what constitutes the object 1. The object 1 exists independently of
the symbol table. You can create bindings between that object and one
or more identifiers, but you can do that with any object.
So, object_id’s for Fixnum’s are synthetic. To think
that those object_id’s point to a location in a memory area that
stores the 32-bit 000…001 (in a 32-bit machine/OS) is to contradict
the meaning of immediacy and defeat the very efficiency that immediate
values offer.
I don’t think object id’s exactly point anywhere. Objects happen to
have unique ids, all of which are synthetic in the sense that they
are, themselves, not the object.
- Now please consider the following supplement to the statements
above:
a += 1; show (a) => Got 2; class = Fixnum; object_id = 5; v >> 1
= 2
For a += 1 you could substitute anything, like a = 300. It’s a
completely new assignment, and completely obliterates any previous
binding.
show (a) => Got 2; class = Fixnum; object_id = 5; v >> 1 = 2
show (b) => Got 1; class = Fixnum; object_id = 3; v >> 1 = 1
The assignment of “a += 1†to “a†changed a’s object_id to embed a new
value: 2.
I’m not sure what you mean by the object_id embedding a value. I would
forget about object_id’s, and just look at the objects.
Despite that change of 1 to 2 in a’s object, “b†remains
set to 1. “b†did not suffer the calamity of a universal change of
all Fixnum 1’s to 2’s.
But there is no “a’s object” across multiple assignments. The
identifier a has absolutely no continuity of consciousness, so to
speak. It’s a reusable, disposable, ad hoc label that can be glued on
to any number of objects in succession. The identifier itself does not
maintain state, and does not “know” how many times it has been used.
a = “hi”
a = “bye”
The second line has absolutely no relation to, or dependency on, the
first. And a += 1 is, essentially, just shorthand for a = a + 1 (i.e.,
all the +=, -=, etc. operators are assignment operators).
So when you do a += 1, you’re explicitly saying that you are
discarding any previous binding of a, and creating a new one. Of
course, you can only use this shortcut if a has a + method. But it’s
an assignment nonetheless; the calling of the method is not, itself,
an assignment operation. You could equally do:
b = a + 1
a = b
- Conclusion:
a += 1 is equivalent to a++’s natural meaning. In fact, we further
“Natural”? 
show(b) => Got 1; class = Fixnum; object_id = 3; v >> 1 = 1
it’ll work fine for non-positives, also… A compiler change to allow
“def ++†is necessary to finally add ++ to Fixnum.
I know we’ve been around the block a few times in this thread already,
but the bottom line is that method calls don’t affect local variable
bindings. The parser could presumably be trained to treat ++ as an
assignment operator, but Matz’s view of this has always been that he
doesn’t want assignment semantics to be delivered in something that
looks like a non-assignment idiom from other languages.
The most important example, I think, is this one:
str = “hi”
=> “hi”
str.object_id
=> 1309270
str.succ!
=> “hj”
str
=> “hj”
str.object_id
=> 1309270
a = 1
=> 1
a.object_id
=> 3
a.succ!
NoMethodError: undefined method `succ!’ for 1:Fixnum
You can’t increment a in place because the messages you send to a
(like: “Increment yourself in place!”) are actually being delivered
to an object, not an identifier.
In that sense, the fact that the identifier holds an immediate value
is actually of secondary interest. Even if it didn’t, you’d still be
sending a message to an object. The final destination of a message is
never an identifier; it’s always an object. So what you’re asking for
has to make complete sense in terms of the object.
David
–
The Ruby training with D. Black, G. Brown, J.McAnally
Compleat Jan 22-23, 2010, Tampa, FL
Rubyist http://www.thecompleatrubyist.com
David A. Black/Ruby Power and Light, LLC (http://www.rubypal.com)