On Monday 24 March 2008, Adam A. wrote:
def changeit var
var = 20
end
changeit x
puts x
==> 20
In ruby you pass the object to the method, not a reference to the
variable.
This means that, if you change the object, changes will affect every
variable
which contains the object. On the other hand, changing the object
contained in
the argument of the method (that is, writing var = 20) won’t affect any
other
variable. This means that if some classes are unchangeable (such as all
kind
of numbers and symbols), you can’t do what you want. Other classes
provide
methods which change them in place. As I said, such changes will affect
every
variable which points to the object. Here are some examples which should
make
things clearer:
def m1 str
str.upcase
end
def m2 str
str = “a string”
end
def m3 str
str.upcase!
end
x = “test”
m1 x
puts “After m1 x is: #{x}”
m2 x
puts “After m2 x is: #{x}”
m3 x
puts “After m3 x is: #{x}”
The output is:
After m1 x is: test
After m2 x is: test
After m3 x is: TEST
m1 calls String#upcase, which is a non-destructive method (that is, a
method
which doesn’t change its receiver) and does nothing else. Of course,
this
doesn’t change x.
m2 sets the local variable str, which initially contains the argument
passed
to the method, to a different value, “a string”. In C++, if the argument
was a
reference, this would have also set x to “a string”. In ruby it doesn’t.
m3 calls a destructive method on str. A destructive method changes its
receiver, so the contents of the object contained by str change (notice
that
this is different from the previous case, where a new object was put
into
str). Since str and x contain the same object, x also changes. A method
like
this can be used to achieve the result you wanted, but it can be written
only
if the argument has a destructive method which does what you need (for
example, you couldn’t have done the same for an Integer, since it
doesn’t have
destructive methods).
I hope this helps
Stefano