Language deisng question and stinrgs and object id's

a = "string"
b = "string"

causes three objects with different object id's to be created.

irb(main):001:0> a = "string"
=> "string"
irb(main):002:0> b = "string"
=> "string"
irb(main):003:0> "string".object_id
=> 19087248
irb(main):004:0> a.object_id
=> 21660552
irb(main):005:0> b.object_id
=> 22419972

Yet
  a = "string"
  b = a
only causes two objects to be created.

irb(main):001:0> a = "string"
=> "string"
irb(main):002:0> b = a
=> "string"
irb(main):003:0> "string".object_id
=> 22106544
irb(main):004:0> a.object_id
=> 22650984
irb(main):005:0> b.object_id
=> 22650984

Yes, I know that one can do

  a = "string"
  b = a.clone

I understand what's happening. I just don't know why the language designer(s) decided on -- what is to me -- surprising behavior.

So I have a Car Talk Puzzler (for which I do not have an answer): How would I initialize a bunch of strings so that they are clones rather than the same object?

In other words how would I do the following which is invalid Ruby.

a = b.clone = c.clone = "How to clone?"

a = "string"
b = "string"

causes three objects with different object id's to be created.

It actually causes just two objects to be created.

irb(main):001:0> a = "string"
=> "string"
irb(main):002:0> b = "string"
=> "string"
irb(main):003:0> "string".object_id
=> 19087248

This one is a new and different thing that is not related to your
above two lines of code at all.

irb(main):004:0> a.object_id
=> 21660552
irb(main):005:0> b.object_id
=> 22419972

I think what you are missing is that a literal String creates a new
string object. The fact that the characters are the same doesn't mean
it's the same object:

1.9.2p290 :001 > "string".object_id
=> 14124100
1.9.2p290 :002 > "string".object_id
=> 14101660
1.9.2p290 :003 > "string".object_id
=> 14081660
1.9.2p290 :004 > "string".object_id
=> 14068260

Yet
a = "string"
b = a
only causes two objects to be created.

It actually only causes one object to be created, see above.

irb(main):001:0> a = "string"
=> "string"
irb(main):002:0> b = a
=> "string"
irb(main):003:0> "string".object_id
=> 22106544
irb(main):004:0> a.object_id
=> 22650984
irb(main):005:0> b.object_id
=> 22650984

A possible misunderstanding here would be to miss the difference
between an object and a variable. A variable is a reference to an
object. Several variables can reference the same object. Assigning
variables only changes what they reference, not the objects
themselves.

Yes, I know that one can do

a = "string"
b = a.clone

I understand what's happening. I just don't know why the language designer(s) decided on -- what is to me -- surprising behavior.

I think that having objects be a separate concept from the variables
that reference them is pretty common, and provides very nice language
semantics.
Just think that a literal string is a new object every time it
appears, the same with hashes, for example.

So I have a Car Talk Puzzler (for which I do not have an answer): How would I initialize a bunch of strings so that they are clones rather than the same object?

In other words how would I do the following which is invalid Ruby.

a = b.clone = c.clone = "How to clone?"

1.9.2p290 :005 > a = (b = (c = "How to clone?").clone).clone
=> "How to clone?"
1.9.2p290 :006 > [a.object_id, b.object_id, c.object_id]
=> [14045460, 14045480, 14045520]
1.9.2p290 :007 > [a,b,c]
=> ["How to clone?", "How to clone?", "How to clone?"]

Jesus.

···

On Sat, Jan 14, 2012 at 3:38 PM, Ralph Shnelvar <ralphs@dos32.com> wrote:

Hi,

I understand what's happening. I just don't know why the language designer(s) decided on -- what is to me -- surprising behavior.

String literals create clone of strings each time they are evaluated,
because strings in Ruby are mutable, so I'd like to avoid literal
modification bugs. The other option is to make string literals
immutable, but that what I didn't choose.

Strings from literals shares body so that they don't consumes much
memory or copying cost.

              matz.

···

In message "Re: Language deisng question and stinrgs and object id's" on Sat, 14 Jan 2012 23:38:00 +0900, Ralph Shnelvar <ralphs@dos32.com> writes:

Or does it create 4 objects?

In other words, is the first "string" object created and then cloned?

Is there a way to see the object id's of the variable "a" and "string" in the first statement?

···

On Sat, Jan 14, 2012 at 3:38 PM, Ralph Shnelvar <ralphs@dos32.com> wrote:

a = "string"
b = "string"

causes three objects with different object id's to be created.

It actually causes just two objects to be created.

I think that's exactly what is causing your misunderstanding. The
variable a is not an object. It doesn't have an object_id. It's just a
reference, a pointer to an object. The only object in a = "string", is
the object created by Ruby when it evaluates the string literal. When
you then say a.object_id, what you are doing is sending the message
"object_id" to the object referenced by a.

Jesus.

···

On Sat, Jan 14, 2012 at 4:16 PM, Ralph Shnelvar <ralphs@dos32.com> wrote:

> On Sat, Jan 14, 2012 at 3:38 PM, Ralph Shnelvar <ralphs@dos32.com> wrote:

a = "string"
b = "string"

causes three objects with different object id's to be created.

> It actually causes just two objects to be created.

Or does it create 4 objects?

In other words, is the first "string" object created and then cloned?

Is there a way to see the object id's of the variable "a" and "string" in the first statement?

Jesús,

Saturday, January 14, 2012, 9:03:56 AM, you wrote:

···

On Sat, Jan 14, 2012 at 4:16 PM, Ralph Shnelvar <ralphs@dos32.com> wrote:

> On Sat, Jan 14, 2012 at 3:38 PM, Ralph Shnelvar <ralphs@dos32.com> wrote:

a = "string"
b = "string"

causes three objects with different object id's to be created.

> It actually causes just two objects to be created.

Or does it create 4 objects?

In other words, is the first "string" object created and then cloned?

Is there a way to see the object id's of the variable "a" and "string" in the first statement?

I think that's exactly what is causing your misunderstanding. The
variable a is not an object. It doesn't have an object_id. It's just a
reference, a pointer to an object. The only object in a = "string", is
the object created by Ruby when it evaluates the string literal. When
you then say a.object_id, what you are doing is sending the message
"object_id" to the object referenced by a.

Jesus.

Thank you. It is a good explanation.

Is there a way to see the object id's of the variable "a" and "string" in the first statement?

Thank you. It is a good explanation.

Is there a way to see the object id's of the variable "a" and "string" in
the first statement?

You said it was a good explanation, but your question makes it obvious that
you did not understand it.

Allow me to explain the way I think about these things. This is a
simplification that ignores several key points, but it is a useful mental
model.

We deal with two things in Ruby: names and objects. Objects have IDs and
reference counts but no names, and live in a fuzzy cloud out in memory
somewhere. Names do not have IDs, and live in dictionaries.

A name is bound to exactly one object. An object can be bound to many
names, and it doesn't know which names they are. The object simply exists
without a name.

When you say this in Ruby:
    "hello
that creates a nameless string object in the fuzzy cloud. That object has
no references, so it will almost immediately be removed by the garbage
collector.

When you say this:
    a = "hello"
that also creates a nameless string object in the fuzzy cloud. That object
is then bound to the name "a". "a" is not an object. It is a name that is
bound to an object. In that example, there is only ONE object. Since the
object itself is nameless, the only way to get to it is through its
bindings. So, to find the object ID of "hello", we have to go through the
name "a".

Now, say I do this:
    b = "hello"
This creates a brand new nameless string object in the fuzzy cloud, and
binds that object to the name "b".

Now, say I do this:
    c = b
This does NOT create any new objects. Instead, it takes the object bound
to the name "b", and binds it to the name "c". That nameless string object
now has two bindings. It doesn't know the names of its bindings, but it
knows how many there are.

So, when you ask this:

Is there a way to see the object id's of the variable "a" and "string" in
the first statement?

the question doesn't make sense. When you say "a.object_id", you are
asking the name "a" to tell you the object ID of the object to which it is
bound. That IS the object ID of the string. You cannot ask for the object
ID of "string" except to go through one of the names to which it is bound.
When you say
    "string".object_id
that creates a brand new object without a name, and tells you its ID. That
object will immediately be deleted, since it has no references.

···

Ralph Shnelvar <ralphs@dos32.com> wrote:
--
Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.

To stick in my oar: Ralph, if you're familiar with pointers in
languages like C and C++, you can think of these "references" Tim
speaks of, as being like pointers, and the variables as being like,
well, variables. You can assign a pointer value to any number of
variables, and assign one variable to another, which just copies the
pointer... or you can assign a variable a new pointer value. (If
you're not familiar with pointers, then, well, never mind....)

-Dave

···

On Sat, Jan 14, 2012 at 20:41, Tim Roberts <timr@probo.com> wrote:

Ralph Shnelvar <ralphs@dos32.com> wrote:

Thank you. It is a good explanation.

Is there a way to see the object id's of the variable "a" and "string" in
the first statement?

You said it was a good explanation, but your question makes it obvious that
you did not understand it.

--
Dave Aronson, President, Dave Aronson Software Engineering and Training
Ruby on Rails Freelancing (Northern Virginia, Washington DC, or Remote)
DaveAronson.com, Codosaur.us, Dare2XL.com, & RecruitingRants.com (NEW!)
Specialization is for insects. (Heinlein) - Have Pun, Will Babble! (me)