Re: Set::setps error? Twitter.m's OOP-like approach?

*To*: mathgroup at smc.vnet.net*Subject*: [mg104811] Re: Set::setps error? Twitter.m's OOP-like approach?*From*: Erik Max Francis <max at alcyone.com>*Date*: Tue, 10 Nov 2009 06:02:59 -0500 (EST)*References*: <hconr9$1lj$1@smc.vnet.net> <hcr7jc$8nb$1@smc.vnet.net>

ragfield wrote: > On Nov 3, 2:58 am, Erik Max Francis <m... at alcyone.com> wrote: >> The deposit function doesn't work, though: >> >> In[6]:= a = create["test", 100] >> >> Out[6]= Account["test", 100] >> >> In[7]:= getBalance[a] >> >> Out[7]= 100 >> >> In[8]:= deposit[a, 25] >> >> During evaluation of In[8]:= Set::setps: Account[test,100] in the part >> assignment is not a symbol. >> >> >> Out[8]= 125 >> >> In[9]:= getBalance[a] >> >> Out[9]= 100 >> >> But here's what I'm confused; if I do what getBalance does manually, it >> works fine: >> >> In[10]:= a[[BALANCE]] += 25 >> >> Out[10]= 125 >> >> In[11]:= a >> >> Out[11]= Account["test", 125] >> >> The Set::setps error is about Blocks so I suppose I'm running into some >> scoping issue but I don't follow what it is. What am I missing here? >> What's the right way to write getBalance? > > By the time deposit[] is called "a" has already evaluated to Account > ["test", 100], which means a[[BALANCE]] += 25 at that point really > means 100 += 25. What you are looking for is "call by reference" > behavior, and the way to get it is to use one of the Hold* > attributes. In this case you want to first argument of your deposit[] > function to remain unevaluated so the actual symbol "a" is passed into > the function in rather than the value of "a". This is true but here's what's confusing me, and it's obviously a misunderstanding of how Mathematica treats objects and what object mutation means in Mathematica (if indeed that's really allowed in any meaningful sense in Mathematica). If we continue where I left off, I can't mutate the value of `a` as above, but I _can_ test it against the global value of `a` with the `===` operator and verify that it's the same object (repeating just enough of the definitions to get the idea): In[67]:= {NAME, BALANCE} = Range[2]; create[name_, balance_] := Account[name, balance] getName[account_Account] := account[[NAME]] getBalance[account_Account] := account[[BALANCE]] deposit[account_Account, amount_] := account[[BALANCE]] += amount In[90]:= a = create["globals", 100] Out[90]= Account["globals", 100] In[91]:= isTheSameAsTheGlobalAQ[account_Account] := account === a In[92]:= x = a Out[92]= Account["globals", 100] In[95]:= isTheSameAsTheGlobalAQ[x] Out[95]= True So I can verify it's the same object, but I can't mutate it -- that generates the aforementioned Set::setps error. But doing it manually with a itself works fine. How come? What is it about Mathematica and values that I'm not getting? It's obviously something fundamental, but I haven't encountered it in a book before. Clearly Mathematica has a more functional approach, so what I'm doing is naughty anyway. Do I take it that the idea of mutating an object in a local context and expecting it to have wider-ranging results (as, say, in other languages like Python or Java or Lisp) is just simply mistaken? -- Erik Max Francis && max at alcyone.com && http://www.alcyone.com/max/ San Jose, CA, USA && 37 18 N 121 57 W && AIM/Y!M/Skype erikmaxfrancis Can I walk with you / 'Till the day that my heart stops beating -- India Arie