MathGroup Archive 2000

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

Search the Archive

Re: string-variable-Set-snarl

  • To: mathgroup at smc.vnet.net
  • Subject: [mg22498] Re: [mg22491] string-variable-Set-snarl
  • From: Hartmut Wolf <hwolf at debis.com>
  • Date: Wed, 8 Mar 2000 02:22:39 -0500 (EST)
  • Organization: debis Systemhaus
  • References: <200003050524.AAA14078@smc.vnet.net>
  • Sender: owner-wri-mathgroup at wolfram.com

Dear James, 
and all of the community,

yesterday I answered to your posting

James Fuite and Tania Nordli schrieben:
> 
> Dear Advanced Mathematica Users,
> 
>  The following is a short and perhaps trivial problem that has caused me
> some frustration.  I cannot write a program that allows me to change the
> value of any given variable if given the name of the variable as a
> string.  What follows is an equivalent situation.  Let
> 
> In[3]=      {cow = Random[], emu = Random[], ant = Random[]}
> Out[3]=    {0.2, 0.3, 0.4}
> 
>        . . . . some selection process . . . .
> 
> In[25]=      animalname
> Out[25]=    cow
> 
> In[25]=     Head[animalname]
> Out[25]=   String
> 
> Given a string, here "cow", corresponding to a variable, here cow, I
> cannot clear or set a value for the variable itself.  Of course I cannot
> use Clear[cow] or cow = 2 because I do not know which variable will be
> chosen, as represented by the variable animalname.  My lame attempts
> such as Clear[animalname] or ToExpression[animalname] = 2 only fail to
> affect cow - it seems that I am caught trying to work on the wrong side
> of the equals sign (Set)!  My goal would be a line such as:
> 
> In[28]=      ToExpression[animalname]
> Out[28]=    2
> 
> which I think would imply that cow = 2 and has thus been affected.  Who
> can guide me from line 25 to line 28?  What are the general
> considerations?
> 
>    Sincerely,
>    James J. Fuite.


...yet my answer is either overly complex, or flawed somewhat. I will
not quote it here, instead give some explanation of my reasoning -- and
a new, better solution -- and not avoid being somewhat lengthy. But I
think what I found out deserves it, since it is of fundamental
importance.

The base problem behind your quest is: "how do I get at the
*unevaluated* symbol, given it's name?" If the symbol has no value,
Symbol[<symbol name>] will do, but if the symbol already has got a
value, whenever you wan't to evaluate Symbol[<symbol name>] to get at
the symbol itself, evaluation will proceed further, which excludes its
use at the lhs of Set. It's only Wolfram Inc. who could prevent that.

A rude solution to this problem would be to Clear the symbol beforehand
-- since it is going to be reset:

In[1]:= Attributes[setsymbol] = {HoldAll};

In[2]:= setsymbol[s_String, rhs_] := 
   (Clear[s]; Evaluate[Symbol[s]] = Unevaluated[rhs])

In[3]:= 
setsymbol[s_Symbol, rhs_] := Unevaluated[s] = Unevaluated[rhs]
 

Then...

In[4]:= setsymbol["cow", 11];
In[5]:= cow
Out[5]= 11

... of course works, but you can't do

In[6]:= setsymbol["cow", cow + 1]
$RecursionLimit::"reclim": "Recursion depth of \!\(256\) exceeded."
Out[6]= 254 + Hold[cow + 1]

In[7]:= cow
$RecursionLimit::"reclim": "Recursion depth of \!\(256\) exceeded."
Out[7]= 255 + Hold[cow + 1]


To avoid this you may give setsymbol only the HoldFirst attribute:


In[1]:= Attributes[setsymbol] = {HoldFirst};
In[2]:=
setsymbol[s_String, rhs_] := (Clear[s]; Evaluate[Symbol[s]] = rhs)
In[3]:=
setsymbol[s_Symbol, rhs_] := Unevaluated[s] = rhs
 
...and then

In[4]:= setsymbol["cow", 11];
In[5]:= cow
Out[5]= 11

In[6]:= setsymbol["cow", cow + 1];
In[7]:= cow
Out[7]= 12

But now we have destroyed the semantics of Set, i.e. the rhs must always
be evaluated (or if you wrap with enough layers of Unevaluated, you'll
get back the problem above).

It was my goal to keep the exact semantics of Set. The idea was to
register the variables of the problem at hand *unevaluated* such that
mysymbol[<symbol name>] :> Unevaluated[symbol]. If you know all your
variables (or variable names for that matter) in advance before your
calculation, then you may register them and go on.

But perhaps this might become arkward; so my idea was to register the
variables at their first use (with setsymbol). The program published
yesterday does that, yet there remains a problem when the variable has
been (perhaps inadvertendly) used before. So I got caught back by the
initial ploblem I wanted to avoid. I lost my nerves and introduced that
Clear -- though only at their first "legal" use.


But this morning I found out a much better way! Here it is:

In[1]:= mysymbol[s_String] := Symbol[s]

In[2]:= mysymbol[s_Symbol] := Unevaluated at Unevaluated[s]

In[3]:= Attributes[setsymbol] = {HoldAll};
In[4]:= 
setsymbol[s_, rhs_] := ((#1 = #2) &)[mysymbol[Unevaluated[s]], 
    Unevaluated[rhs]]

In[5]:= 
$NewSymbol = (With[{s = Symbol[#1]}, 
          mysymbol[#1] = Unevaluated at Unevaluated[s]] &);


Let me give a short discussion: If a variable is given as a symbol, then
mysymbol just returns that symbol unevaluated, and that unevaluated
symbol is inserted at the lhs of Set, whereas the rhs also is inserted
unevaluated. Further progress is now identical to s = rhs. If a variable
is given as a string, it's name, then if it's registered
mysymbol[<variable name>] retrieves the unevaluated symbol, that is
inserted at the lhs of Set, ok. If the variable has not been registered
before, and if it was not existent, then the symbol is generated with
Symbol[<symbol name>] (which cannot evaluate further) and is inserted at
the lhs of Set.

This works as long as there are no unregistered variables. Here now
$NewSymbol comes in. This system symbol is a hook for a function that
intercepts the process of generating a new symbol. We use it to register
any variable in status nascendi!

With is used there as to get the evaluated Symbol[<symbol name>], i.e.
the new symbol itself into the rhs of the definition. Unevaluated
appears twice since evaluation of this expression (Set) removes one
Unevaluated and the second one is left in the definition, that one we
need so urgent!


Kind regards, Hartmut


  • Prev by Date: Re: string-variable-Set-snarl
  • Next by Date: Re: Detect pairs, tripples in a list
  • Previous by thread: Re: string-variable-Set-snarl
  • Next by thread: Re: string-variable-Set-snarl