MathGroup Archive 2009

[Date Index] [Thread Index] [Author Index]

Search the Archive

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

  • To: mathgroup at smc.vnet.net
  • Subject: [mg104826] Re: [mg104811] Re: Set::setps error? Twitter.m's OOP-like approach?
  • From: DrMajorBob <btreat1 at austin.rr.com>
  • Date: Wed, 11 Nov 2009 04:26:21 -0500 (EST)
  • References: <hconr9$1lj$1@smc.vnet.net> <hcr7jc$8nb$1@smc.vnet.net>
  • Reply-to: drmajorbob at yahoo.com

> So I can verify it's the same object, but I can't mutate it

Help says: "lhs === rhs yields True if the expression lhs is identical to  
rhs, and yields False otherwise." That means the two EXPRESSIONS are  
identical, not that the two are the same OBJECT.

For instance:

First I set x and y to the same value:

x = f[5]
y = x

f[5]

f[5]

They test identical (SameQ):

x === y

True

Now I change x:

x = 2

2

But y is unchanged, since x and y are different objects:

y

f[5]

Now I define a function:

Clear[f]
SetAttributes[f, HoldFirst]
f[x_] := (x++; Null)

Next I pass x to f, and show the new value of x:

f[x]
x

3

Now look at the value of y, again:

y

Increment::rvalue: 5 is not a variable with a value, so its value cannot  
be changed. >>

Do the same again:

y

Increment::rvalue: 5 is not a variable with a value, so its value cannot  
be changed. >>

We get exactly the same error message, since y is still f[5].

Test that:

y===f[5]

Increment::rvalue: 5 is not a variable with a value, so its value cannot  
be changed. >>
Increment::rvalue: 5 is not a variable with a value, so its value cannot  
be changed. >>
True

Yes, y is still f[5], even though the error appears again (once for the  
left hand side, again for the right).

Now change f, and show the value of y again.

f = Sin@# &;
y

Sin[5]

Bobby

On Tue, 10 Nov 2009 05:02:59 -0600, Erik Max Francis <max at alcyone.com>  
wrote:

> 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?
>


-- 
DrMajorBob at yahoo.com


  • Prev by Date: Re: Mathematica skill level snippet(s)
  • Next by Date: Another NMinimize w/ NDSolve question...
  • Previous by thread: Re: Set::setps error? Twitter.m's OOP-like approach?
  • Next by thread: Re: Set::setps error? Twitter.m's OOP-like approach?