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