From: "Michael T. Richter" Date: 2007-09-30T20:58:15+09:00 Subject: Re: a = Dog.new # a is not a pointer and not a reference? --=-RpwYA6ZJWIRueyZpGlEz Content-Type: multipart/related; type="multipart/alternative"; boundary="=-KNQF7uooAOCu7u7YrWkl" --=-KNQF7uooAOCu7u7YrWkl Content-Type: multipart/alternative; boundary="=-KIZHje2jedaXqVNnfiqj" --=-KIZHje2jedaXqVNnfiqj Content-Type: text/plain Content-Transfer-Encoding: quoted-printable On Sun, 2007-30-09 at 15:39 +0900, SpringFlowers AutumnMoon wrote: > how about just a.set_value(3) vs a->set_value(3). what i mean is just=20 > the "." and "->" difference. using a "." in Ruby and "->" in C or C++.=20 > If I think of "a" as a pointer and "." as "->", will that get in trouble=20 > and have any discrepancy for other things. I think part of your confusion here, SFAM, is that you're talking about "pointers" and "references" as if they were distinct entities. They are not. A pointer is a kind of reference; an implementation detail, in effect. So C, you see, has references (as do various assemblers, in the same general form). They are called "pointers" and have some ugly syntax and semantics: int a =3D 5; /* a is a box holding 5 */ int *b =3D &a; /* b is a box that points to 5 */ int c =3D a; /* c is a box holding 5 */ int d =3D *b; /* d is a box holding 5 */ a =3D 6; /* a now holds 6, b points to 6, c & d are boxes holding 5 */ Note how ugly the reference syntax is in C? You have to explicitly tell it that it is a reference (int *b) and you have to use special syntax to turn a variable into a reference (&a). Later, when you want to use the value of the referent, you need, again, to explicitly say so (*b). (Now, to be fair, there are some pretty cool tricks you can do with C's references, but we're in the realm of using chainsaws to clip our fingernails when we use a feature with that much power to do routine application things.) References in C++ are either the old-style C references (pointers) or a newer breed of reference which they confusingly call... references. As if they were something different. Now the syntax is a bit friendlier: int a =3D 5; // a is a box holding the value 5 int &b =3D a; // b is a box holding the location of the box a int c =3D a; // c is a box holding the value 5 int d =3D b; // d is a box holding the value 5 a =3D 6; // a now holds 6, b points to 6, c and d & boxes holding 5 Note that you still have to specifically say that a variable is a reference (int &b), but you no longer have to take addresses explicitly (no &a) and you no longer have to tell the compiler that you mean the value pointed to, not its location (no *b). Under the covers, though, it's all the same thing: boxes with values and other boxes that point to those values. There's only a few minor advantages to using references over pointers: 1. The cleaner syntax. (You can't make the mistake of accidentally using an address when you mean the value.) 2. The lower power. (Yes, this is an advantage: you're clipping your nails with a belt sander instead of a chainsaw. :D) 3. The compiler can better reason about the data involved and can silently optimize away the actual references if it turns out that using the data straight is safer and won't have any semantic impact. Ruby's references are a completely different implementation. And, indeed, Ruby's variables in general are radically different in nature. A variable in Ruby is more like a file handle (another form of reference, incidentally) or an array index (yet another form of reference) than it is like a C or C++ variable (a box with a value). a =3D 5 # a.object_id is 11 in my irb session. b =3D a # a and b.object_id are both 11. c =3D a # a, b and c.object_id are all 11. d =3D b # a, b, c and d.object_id are all 11. a =3D 6 # a.object_id is now 13. b, c and d.object_id are all still 11. Note that here things are radically different from C/C++ (whose "pointers" and "references" are basically the same thing under the covers and implemented in mostly the same way). a is not a box with a value. a is an abstract label (value 11) that is used by the Ruby runtime to find the value 5. You can view it as a "pointer" of sorts, but it's probably better to think of it like you'd think of a file handle returned from an fopen() system call: it's an opaque data structure containing a lot of information behind the scenes, one of which happens to be an indirect reference to the value 5. When we assign a to b, b is now the very same thing. It's just another name, in effect, for exactly the same object information (which happens to indirectly reference the value 5). As we proceed to c (from a) and d (from b), we're basically just attaching more names to the very same information. It's sort of like doing fopen() several times on the same file (as long as you ignore issues like seeking, etc.). At the very end, when I assign 6 to a, what I'm really doing is making a brand new "handle" that contains, among other things, an indirect reference to the value 6. This does not change, in any way, the values assigned to b, c or d. Those are still handles to the same data structure with its indirect reference to 5. So.... Short version: Ruby variables are all references. So are C++ "references" and C/C++ "pointers". But the Ruby implementation is radically different from the C/C++ versions. The sooner you leave your C/C++-derived notions of what variables "really" are and how they "really" work behind, the sooner you will understand the subtler aspects of Ruby's semantics. If you're still having troubles figuring this out (or if anybody else is quietly watching this and still getting confused), drop me a line by private email and I'll hack together some C++ code that kinda-sorta does the same thing as Ruby so you can understand what's going on in a variable structure you're more familiar with. --=20 Michael T. Richter (GoogleTalk: ttmrichter@gmail.com) We should sell bloat credits, the way the government sells pollution credits. Everybody's assigned a certain amount of bloat, and if they go over, they have to purchase bloat credits from some other group that's been more careful. (Bent Hagemark) --=-KIZHje2jedaXqVNnfiqj Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: quoted-printable On Sun, 2007-30-09 at 15:39 +0900, SpringFlowers AutumnMoon wrote:
how about just a.set_value(3) vs a->set_value(3)=
.  what i mean is just 
the "." and "->" difference.=
  using a "." in Ruby and "->" in C or C++. 
If I think of "a" as a pointer and "=
." as "->", will that get in trouble 
and have any discrepancy for other things.

I think part of your confusion here, SFAM, is that you're talking about &qu= ot;pointers" and "references" as if they were distinct entit= ies.  They are not.  A pointer is a kind of reference; an impleme= ntation detail, in effect.  So C, you see, has references (as do vario= us assemblers, in the same general form).  They are called "point= ers" and have some ugly syntax and semantics:

int a =3D 5;      /* a is a box holding 5 = */
int *b =3D &a;    /* b is a box that points to 5= */
int c =3D a;      /* c is a box holding 5 = */
int d =3D *b;     /* d is a box holding 5 */
a =3D 6;          /* a= now holds 6, b points to 6, c & d are boxes holding 5 */

Note how ugly the reference syntax is in C?  You have to explicitly te= ll it that it is a reference (int *b) and you have to use special syntax to= turn a variable into a reference (&a).  Later, when you want to u= se the value of the referent, you need, again, to explicitly say so (*b).&n= bsp; (Now, to be fair, there are some pretty cool tricks you can do with C'= s references, but we're in the realm of using chainsaws to clip our fingern= ails when we use a feature with that much power to do routine application t= hings.)

References in C++ are either the old-style C references (pointers) or a new= er breed of reference which they confusingly call... references.  As i= f they were something different.  Now the syntax is a bit friendlier:<= BR>
int a =3D 5;     // a is a box holding the valu= e 5
int &b =3D a;    // b is a box holding the locat= ion of the box a
int c =3D a;     // c is a box holding the valu= e 5
int d =3D b;     // d is a box holding the valu= e 5
a =3D 6;         // a now h= olds 6, b points to 6, c and d & boxes holding 5

Note that you still have to specifically say that a variable is a reference= (int &b), but you no longer have to take addresses explicitly (no &= ;a) and you no longer have to tell the compiler that you mean the value poi= nted to, not its location (no *b).  Under the covers, though, it's all= the same thing: boxes with values and other boxes that point to those valu= es.  There's only a few minor advantages to using references over poin= ters:
  1. The cleaner syntax.  (You can't make the mi= stake of accidentally using an address when you mean the value.)
  2. The lower power.  (Yes, this is an advantag= e: you're clipping your nails with a belt sander instead of a chainsaw. )
  3. The compiler can better reason about the data in= volved and can silently optimize away the actual references if it turns out= that using the data straight is safer and won't have any semantic impact.

Ruby's references are a completely different implementation.  And, ind= eed, Ruby's variables in general are radically different in nature.  A= variable in Ruby is more like a file handle (another form of reference, in= cidentally) or an array index (yet another form of reference) than it is li= ke a C or C++ variable (a box with a value).

a =3D 5    # a.object_id is 11 in my irb session.
b =3D a    # a and b.object_id are both 11.
c =3D a    # a, b and c.object_id are all 11. d =3D b    # a, b, c and d.object_id are all 11.
a =3D 6    # a.object_id is now 13.  b, c and d= .object_id are all still 11.

Note that here things are radically different from C/C++ (whose &quo= t;pointers" and "references" are basically the same thing un= der the covers and implemented in mostly the same way).  a is not a bo= x with a value.  a is an abstract label (value 11) that is used by the= Ruby runtime to find the value 5.  You can view it as a "pointer= " of sorts, but it's probably better to think of it like you'd think o= f a file handle returned from an fopen() system call: it's an opaque data s= tructure containing a lot of information behind the scenes, one of which ha= ppens to be an indirect reference to the value 5.  When we assign a to= b, b is now the very same thing.  It's just another name, in e= ffect, for exactly the same object information (which happens to indirectly= reference the value 5).  As we proceed to c (from a) and d (from b), = we're basically just attaching more names to the very same information.  It's sort of like doing fopen() several times on the same file (a= s long as you ignore issues like seeking, etc.).  At the very end, whe= n I assign 6 to a, what I'm really doing is making a brand new "= ;handle" that contains, among other things, an indirect reference to t= he value 6.  This does not change, in any way, the values assigned to = b, c or d.  Those are still handles to the same data structure with it= s indirect reference to 5.

So....

Short version: Ruby variables are all references.  So are C++ "re= ferences" and C/C++ "pointers".  But the Ruby implement= ation is radically different from the C/C++ versions.  The soon= er you leave your C/C++-derived notions of what variables "really"= ; are and how they "really" work behind, the sooner you will unde= rstand the subtler aspects of Ruby's semantics.

If you're still having troubles figuring this out (or if anybody else is qu= ietly watching this and still getting confused), drop me a line by private = email and I'll hack together some C++ code that kinda-sorta does the same t= hing as Ruby so you can understand what's going on in a variable structure = you're more familiar with.

--
Michael T. Richter <ttmri= chter@gmail.com> (GoogleTalk: ttmrichter@gmail.com)
We should sell bloat credits, the way the government sells pollution cre= dits. Everybody's assigned a certain amount of bloat, and if they go over, = they have to purchase bloat credits from some other group that's been more = careful. (Bent Hagemark)
--=-KIZHje2jedaXqVNnfiqj-- --=-KNQF7uooAOCu7u7YrWkl Content-ID: <1191152265.32121.17.camel@isolde> Content-Disposition: attachment; filename=smiley-1.png Content-Type: image/png; name=smiley-1.png Content-Transfer-Encoding: base64 iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAC5UlEQVR42n2TW2hUZxSFv/8/Z6Jz caKJwTGhyWi9glSUglYsRZFWECvYRir6ZL3jJRZLsYJQtAj6oC2IISBqQQg+SKOEKiRStUZ9EbyM NcPEGSXRmMyJTjLnZOb8Z87fh6RCrbhgP+y1914va234P+qAHUAL4I7W78CW0dl/IN7qT86Kh7bu 2ziP5V/MxgzHoVTAHXpMR8df7P91gMfP3EZg27sE2n/aNnfpzl3fIIwgnp3BzScRwsAYOxmjrBJl pzn2SxtHmrPtwDIAY/S46eCOj7/euXsdpeEelJPBVzmEDADguxaenQY0nyyIYzh9U28+LMSAVgHU zZ05IXP1wh60N4Q33I0wgpR8iSF9dGkYt+hgYON7DmawmuLre3y++QnJ7lJcAitajlUgZADlPKXt VpZNP14nvvg0ucCXHD3VybRll6j/LkE2tBuV78IMxthcPx5gkQAas/d/2KLspwDIQJRQzVo85aCd RwgzTCAyC60scqkT+CqHNEPcudvFV3t7z5s1NdXfAvjeINKMgPYYfnEBIcvQvkKX8hT6r+F7NlAC wCv0MXmiAbDatCyLP/58QiaVougFEDKAxkRKA7SP1mpEyC/iey4ClzLDZUJ0xECzUCi2tt/oXNWw /zxKKSorKzFNk6qqqjf+aq3RWmNZFkopbNum9cwawLpjAlc+qn25KhbuQpZ/ipSS8vJytNZIKVFK IYRACIGUEsdxKOYSdD7IADQbQH/mOQ0zYt18UJElk51IMpnEsiwAwuEwvb29pNNpEokEk6KvqBg8 zKGmbgby7DGAnJVTtTVRb96YQI45M8ZT/eESamvjRCIRpJQYxkjeqsblCfcf4PuDD7ie8BuB3/5N 4sXbDwc/i8r8FG/oBsJqJlhWwHPzDPSl6O+5z4vUZSapJn4+nuBsu7oG1L/rmU5NickNKxeG2Lt9 +hvyeZ/LlY7XnGvpIdnDOWA970Ed0ADcAhRgAX8DJ4D5by//A0f8RUIabvq3AAAAAElFTkSuQmCC --=-KNQF7uooAOCu7u7YrWkl-- --=-RpwYA6ZJWIRueyZpGlEz Content-Type: application/pgp-signature; name=signature.asc Content-Description: This is a digitally signed message part -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.3 (GNU/Linux) iD8DBQBG/48/LqyWkKVQ54QRAqdVAJ4o1fqEGesV/L83knIBCs7GWuJeZgCdGI3j 0a3tPvCQ+S2hl6uyGOGvu3U= =ynOR -----END PGP SIGNATURE----- --=-RpwYA6ZJWIRueyZpGlEz--