On Thursday 18 September 2008 05:35 pm, Brian Candler wrote:
> Randy Kramer wrote:
> > So, what is the net effect?  With any of the three syntaxes (a[2] = 
3, 
> > a.[]=(2,4), a.send(:[]=, 2, 5)), I change (assign a new value to) 
the 
> > 3rd element of the array a.
> > 
> > What is the practical point of saying it is not an assignment?
> 
> It just so happens that the semantics of the []= method on an Array 
> object are to replace the x'th element with a pointer to y. However 
> there is no requirement for any object to behave in such a way.
> 
>   class Foo
>     def []=(x,y)
>       puts "Hello #{x}, today is #{y}"
>     end
>   end
>   a = Foo.new
>   a["Randy"] = "Friday"
> 
> It's just a method call. Objects can, in response to method calls, 
> mutate (normally that means change what their instance variables point 
> to; in the case of Array, which is a special built-in class, it means 
> change the underlying hidden data structure)

Hmm, don't know how to express this properly (and maybe it's way off 
base), but are you hinting at the idea that if I were to try []= on an 
immutable data type, then the behavior would not be an assignment. (I'm 
not sure what it would do--report an error, create a new object with a 
different object_id?  (Some quick experiments with a constant seem to 
indicate that is the case (actually, it does both).)

That does seem to be what happens at least for this case:

irb(main):224:0> Const = 3.14
(irb):224: warning: already initialized constant Const
=> 3.14
irb(main):225:0> Const.object_id
=> -606494436
irb(main):226:0> Const = 3.00
(irb):226: warning: already initialized constant Const
=> 3.0
irb(main):227:0> Const.object_id
=> -606517176

So now would I say that this is not an assignment?  Hmm, I was almost 
ready to say yes, but not really--yes, I know it created a new object 
instead of changing the value of the old, but the net effect to any 
program I've written is that where Const used to be 3.14, it is now 
3.00 (I should call this the Indiana legislature assignment).  

> But objects mutating is completely different to assignment.

In what practical way?  I mean, within the Ruby internals, you're 
probably right.  If calling it a method instead of an assignment is 
only to help me remember that, being a method, it could do something 
else, OK, maybe that's helpful, sort of like remembering in C++ that I 
could overload (I think) the = operator.
 
>   var = expr
> 
> means calculate the value of 'expr' (which *always* results in a 
> reference to some object), and store this reference in the local 
> variable 'var' (which is a slot on the stack)

Anyway, we don't have to go any further on this point.  I'm taking that 
free online Ruby course, maybe I'll learn something to change my mind 
there.  If not, I'll just consider it an assignment till something 
bites me--then I'll no doubt (I hope) learn something. ;-)

> This is something I find great about Ruby: everything is a reference. 
In 
> C you have to decide whether you are passing a value or a pointer; in 
> C++ you have to decide whether you are passing a value, a pointer or a 
> reference :-(

Yes, that seems helpful.

> >>   a = malloc(123);  /* a points to some memory */
> >>   c = a;            /* c points to the same memory */
> > 
> > Ok, is there still some magic here?.  Compare (thinking in C):
> > 
> > Given:
> > 
> > char *a;
> > char *c;
> > 
> > Would both of these assignments (in C) work as they would in Ruby:
> > 
> > a = [1, 2, 3]
> > c = a
> 
> You can't do exactly that in C. One possibility is
> 
>   char a[3] = { 1, 2, 3 };
>   char *c;
> 
>   c = a;
> 
> Here a and c are not exactly the same. Arrays in C are just pointers 
to 
> memory, and you could use 'a' and 'c' in any context that a 'char *' 
> pointer would be expected, but whilst you can modify 'c' to point 
> somewhere else, you cannot modify 'a' (e.g. a++ is illegal, as is a = 
b)
> 
> A bit closer to Ruby is:
> 
>   char *a;
>   char *c;
> 
>   a = malloc(3);
>   memcpy(a, "\x01\x02\x03", 3);
> 
>   c = a;

Thanks, I'll have to let some of that percolate some. ;-)

> Note that in Ruby, the expression [1, 2, 3] creates a new object every 
> time it executes. Try for example,
> 
>   10.times { puts [1, 2, 3].object_id }
> 
> The same even applies for Strings:
> 
>   10.times { puts "Hello".object_id }
> 
> There are only a few cases where you get the same object each time 
round 
> (e.g. Fixnums, some Regexp literals, symbols, nil, true, false)

Ok, I guess that goes back to the discussion above--the fact that it is 
a different object doesn't (usually?) make a difference in a program I 
might write.

Thanks!

Randy Kramer
-- 
I didn't have time to write a short letter, so I created a video 
instead.--with apologies to Cicero, et.al.