From: Rob Biedenharn Date: 2006-11-02T23:35:36+09:00 Subject: Re: variable pointer On Nov 2, 2006, at 8:55 AM, Rob Sanheim wrote: > On 11/1/06, dblack@wobblini.net wrote: >> Hi -- >> >> On Thu, 2 Nov 2006, ara.t.howard@noaa.gov wrote: >> >> > On Thu, 2 Nov 2006 dblack@wobblini.net wrote: >> > >> >> It was recently noted on the Rails mailing list that something >> like >> >> that happens in ActiveRecord. Given Person and Address models, >> where >> >> Person has_one Address: >> >> >> >> a = person.address >> >> person.address = Address.find(some_other_address) >> >> puts a # a has changed! >> >> >> >> I find it un-Rubyish and disconcerting (though I'm still >> waiting for >> >> someone to explain the rationale; there may be something I'm >> missing). >> > >> > can you show an example? are you saying that activerecord >> avoids apparent >> > copy-on-write semantics with some trickery? >> >> Here's an example from a program which models Ideas; each Idea >> belongs >> to a Page. >> >> >> i = Idea.find(6) >> => #"6", "id"=>"6", >> "content"=>"Go to Paris"}> >> >> # Save the idea's page in p >> >> p = i.page >> => #"6", >> "title"=>"Domestic travel", "id"=>"6"}> >> >> # Change the idea's page to a different one >> >> i.page = Page.find(7) >> => #"1", >> "title"=>"Foreign travel", "id"=>"7"}> >> >> # Examine the saved page -- it's the new one >> >> p >> => #"1", >> "title"=>"Foreign travel", "id"=>"7"}> >> >> I don't know the rationale. When I (think I'm) assign(ing) an object >> to a variable, I really don't want it to turn out that it's some >> special arrangement whereby the variable is subject to reassignment >> without notice. I expect: >> >> p = i.page >> >> to be exactly equivalent to: >> >> p = Idea.find(i.page.id) >> >> with respect to p. >> > > Wow, that looks nasty. Can you point me to the releveant thread in > the rails group where this was discussed? > > - Rob > > -- > http://www.robsanheim.com > http://www.seekingalpha.com > http://www.ajaxian.com > Why is this so hard to understand? Rails isn't really doing anything magic or really even tricky here -- just "unexpected". You are just confusing references and objects. >> require 'ostruct' => true >> o = OpenStruct.new('page' => "original", 'cover' => "hard") => # >> p = o.page => "original" No surprise there. Let's change the contents of the page. >> o.page.replace("forgery") => "forgery" ...and check in with our variable (aka, object reference): >> p => "forgery" Yup. Still refers to the same String object as o.page. Now let's do an assignment: >> o.page = "restoration" => "restoration" >> p => "forgery" o.page now refers to a new object. But o.page = "restoration" is really just sugar for o.page=("restoration"), right? >> def o.page=(kind); self.page.replace(kind); end => nil Make p refer to the same String object as o.page again: >> p = o.page => "restoration" >> p => "restoration" >> o.page => "restoration" Now this "assignment" calls the newly defined page= method: >> o.page = "imitation" => "imitation" >> p => "imitation" >> p.replace("faux") => "faux" >> o.page => "faux" So the way that variables are references to objects and the syntactic sugar that makes 'o.page = foo' look like assignment even though it's sending foo to the page= method of the o object are just colliding in your brain. -Rob Rob Biedenharn http://agileconsultingllc.com Rob@AgileConsultingLLC.com