----- Original Message ----- 
From: "Rasputin" <rasputin / shrike.mine.nu>
To: "ruby-talk ML" <ruby-talk / ruby-lang.org>
Sent: Friday, June 13, 2003 6:01 PM
Subject: Re: does each work on a copy?


> By 'copy of the reference' I meant:
> 
> ary = %w( a b c d e)
> ary.each { |r| r = "X" }
> 
> r is given a copy of the 'reference' (apology for the Perlism),
> so when you point (ugh, and the Cism) r at "X" you're updating a
> copy of the reference, not the original reference. Is that about right?

It's right "in effect," but you're looking at it
a little differently from the way we do here.

I wouldn't ever use the term "copy of a reference"
in describing Ruby's behavior.

Remember that assignment is *not* an operation on
an object! It's an operation on a variable.

This may confuse those who come from C++. As for
Perl, I don't really know it.

True, a variable "is a reference to an object." But
when you assign to a variable, you're just assigning
to a variable; you're not "assigning to a reference."
It doesn't affect the object referred to at all.

A "reference" is not a "real thing," just a statement
of a relationship, if you know what I mean.

Any assignment "overwrites" the reference that the 
variable had before, but does not affect the object.

Just think in terms of variables and objects. You can
change a variable, and you can change an object. When
you change an object, you are typically changing its
contents.

> And in the below code, 
> 
> string2 = "Hi" 
> is just pointing string2 to a new object, whereas
> string2[0] = "J"
> is editing the object through the string2 reference, just
> as word.upcase! below is doing, as opposed to the |el| el = SPACE
> in my original post.

Again I'd have to say "yes and no."

An additional subtlety for the newbie is that, while
  string[0] = "J"
*looks* like an assignment, it really isn't. I'm not
kidding you here.

The String class has method methods called [] and []=.
The latter is named and invoked in such a way that it
reminds us of assignment; but it's really a method call
on an object. (I said this last week in another context.)

Imagine that these were instead named 'get' and 'set' --
instead of saying
  x = str[0]
  str[0] = y
we could say
  x = str.get(0)
  str.set(0,y)

This makes it clearer that we are actually invoking a 
method on an object, not assigning to a variable.

Invoking a method on an object can potentially change
that object. Assigning to a variable never changes the
onject that the variable referred to before the 
assignment.

As an aside, consider why Ruby does not have C's ++
operator. It looks like an operator (as we're used to
thinking of it that way in C).

This is slightly different from other arguments I've
heard on this topic. I'm making it up as I go along,
so bear with me. :)

But if x++ means x = x + 1, then it's just syntax sugar
for assignment; it's not an operator.

To have ++ as a method/operator that acts on an object
makes no sense in Ruby (for numbers at least).

A number in Ruby is an object, but it is stored as an
immediate value. Conceptually there is only one 5 value
in the whole universe. It's not like strings:

   a = b = "Hello"    # a and b refer to the same object
   c = "Hello"        # c refers to a different object

   d = e = 5          # d, e, and f all refer to the 
   f = 5              #   same object, 5

A ++ *could* be implemented in Ruby as syntax sugar for
assignment (though I don't think Matz would ever do it).

It couldn't be implemented as an operator/method (most
operators in Ruby are really methods). Imagine that we
set x to 5, and then did an x++. Now we have changed 
the *object* 5 to the object 6! Our universe now has
two 6's and no 5's. This is complete and utter nonsense,
unless you have followed Alice down the rabbit hole.
(Not that there's anything wrong with that in general,
but it doesn't improve Ruby.)

Hal