From: Brian Candler Date: 2008-09-19T06:35:12+09:00 Subject: Re: why one array continues to grow after repeated call 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) But objects mutating is completely different to assignment. 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) 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, I > know that the underlying thing is a method, and somehow a[2] = 3 is > syntactic sugar (I guess), for a.[]=(2,3), but in the end, it > accomplishes an assignment. In the case of an Array object, it accomplishes a modification to that object's internal state. >> Yes, that's very important too. You are assigning to a local variable, >> which is just a slot on the stack. A local variable is in fact one of >> the few things which is *not* an object in Ruby. It *holds* a reference >> to an object, but is not an object itself. > > I'm assuming the same is true for any variable in Ruby, not just local > variables? Sure: global variables, instance variables and class variables all live in different places, but they are just holders of references and are not objects in themselves. >> 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; 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) B. -- Posted via http://www.ruby-forum.com/.