From: Rick DeNatale Date: 2009-11-01T05:38:54+09:00 Subject: Re: In-place parameter modification On Sat, Oct 31, 2009 at 5:03 AM, 7stud -- wrote: > Judson Lester wrote: >> Finally: ruby is a pass-by-reference language, so if you actually do >> make >> changes the parameters of a method, the callers variables will change as >> well. > > def test(x) >  x = 10 > end > > num = 5 > test num > puts num > > --output:-- > 5 > > ??? As long as you've been hanging out here, I'm surprised if you are really surprised by this. In order to get completely comfortable with Ruby you need to understand the relationships and differences between objects and variables Objects are instances of classes, and typically have state, in some cases like Fixnums the only state is really the object's identity, and such objects are immutable, if two such objects have different state, then they MUST be different objects. There is only one 1 object and one 5 object. Symbols are similar in that there is only one instance of symbol with a particular value. Some clases have methods which change the state of an object without changing it's identity. String.gsub! is one such method. You can write such mutating methods yourself, clearly for your own classes, but also for core classes which already have mutating methods by writing new methods interms of the existing mutating methods. A variable is not an object, rather it is a temporary binding to a particular object which is established by, and can be changed by an assignment expression, syntactic sugar which disguises an assignment expression (e.g. x += y). Variables include locals, method parameters, instance variables, element slots in arrays, and block arguments (which are distinguished from local variables in Ruby 1.9). So variables can't be mutated, they can only have their binding switched to another variable, if two variables reference the same object, and the binding of one of those variables changes to reference another object, the other variable is unaffected. def test(x) x = 10 end num = 5 test num puts num --output:-- 5 But, again since variables are bindings to objects, if two variables reference the same object, and that object is mutated, then the change in state will by visible through ANY reference to that particular object. x and num are two different variables. At the time test is called, num is bound to 5, inside the context of the invocation of test, x starts out bound to 5, then the assignment changes the binding of x to 1, and leaves the binding of num alone. Imagine the code had been: num=5 x = 1 puts num output: 5 I hope that this is completely unsurprising, I suspect the surprise might come from the assumption that somehow x and num are the same variable because of the formal/actual parameter pairing. In the case of method arguments (and block arguments in Ruby 1.9) the name is local to the method (or block). This means that x and num are indeed not the same variable, but two variables one of which (x) is initialized by the call to refer to the same object resulting from the expression used in the call, which in this cases happen to simply be the variable num. Imagine that we'd called test(num + 1) Here the actual value would be not 5 but 6, and there's no visible variable which corresponds to the actual expression. And even if the FORMAL parameter name were changed: def test(num) num = 10 end num = 5 test num puts num --output:-- 5 The result would be the same, since the names num at the top level, and num inside the test method are two different variables. HTH And of course there's my oldie but goodie: http://talklikeaduck.denhaven2.com/2006/09/13/on-variables-values-and-objects -- Rick DeNatale Blog: http://talklikeaduck.denhaven2.com/ Twitter: http://twitter.com/RickDeNatale WWR: http://www.workingwithrails.com/person/9021-rick-denatale LinkedIn: http://www.linkedin.com/in/rickdenatale