MathGroup Archive 2011

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

Search the Archive

Re: Interaction of Remove and Global variables in a Module

  • To: mathgroup at smc.vnet.net
  • Subject: [mg120134] Re: Interaction of Remove and Global variables in a Module
  • From: Leonid Shifrin <lshifr at gmail.com>
  • Date: Sat, 9 Jul 2011 07:32:58 -0400 (EDT)
  • References: <201107071128.HAA15173@smc.vnet.net>

Bobby,

On Fri, Jul 8, 2011 at 12:16 PM, DrMajorBob <btreat1 at austin.rr.com> wrote:

> So far, I haven't heard a purpose for Remove that ClearAll does not serve
> just as well... without the side-effect of "spoiling" other symbols.
>

Well, just to *Remove* the symbol, as simple as that. There are cases where
you may not wish the symbol to remain in the system. For example, you want
to create it in another context which is also on the $ContextPath, and would
like to avoid shadowing. Also, if one generates a lot of dummy symbols for
some purposes, it is a good practice to Remove them as soon as they are no
longer needed, not to "pollute" the system with them (it takes memory to
hold them, plus a lot of them would negatively impact the performance of the
symbol-table and rule-dispatching mechanism, which are based on
hash-tables). Such cases are relatively rare only because the programming
techniques that manipulate contexts or automatically generate large numbers
of symbols are not widely used. I used them however, and so occasionally
needed to call Remove.

And regardless of this, I think that for the purposes of the example under
discussion, a stand-alone call to Clear or ClearAll that is not immediately
followed by assigning a new definition to a symbol is an invitation for
trouble. The following is IMO marginally acceptable:

ff[fname_Symbol,b_]:=
   Module[{t},Clear[fname];fname[t_]=b*t^2;];

But is still no better that a global variable, even though formally it is a
function. What I'd do instead, as an alternative to a pure function, is to
create a unique symbol, assign the definition(s) to it, and never again
modify it. If we need another function, create another unique symbol. A sort
of immutability for symbol's definitions. Because a symbol that may hold
different definitions at different times in a program, is confusing, and
likely to produce subtle and hard-to-find bugs. You can make run-time
redefinitions of  functions, which is actually a fairly advanced technique
(the simplest case of which is widely known for us as memoization), but this
must be done in a controlled way.

Cheers,
Leonid




>
> Bobby
>
>
> On Fri, 08 Jul 2011 03:53:55 -0500, Leonid Shifrin <lshifr at gmail.com>
> wrote:
>
>  Brian,
>>
>> The problem you encountered is actually more subtle. Remember that when
>> you
>> use Remove (as compared to Clear or ClearAll), the symbol is completely
>> removed
>> from the system. This is a pretty disruptive operation. Now, what should
>> the system do if the symbol you are removing is referenced by some other
>> symbols?
>>  Keeping it there unchanged would mean that the symbol has not been really
>> removed
>> from the system. The solution used in Mathematica is to change a reference
>> to a
>> symbol
>> (say "a") to Removed[a]. In practice, this means that, even when you
>> re-introduce
>> the symbol, those definitions that were involving it are still "spoiled"
>> and
>> can not
>> be used.  IMO, this is a very sensible design, but this is what leads to
>> the
>> behavior
>> that puzzled you. Have a look:
>>
>> f[b_]:=Module[{t},a[t_]=b*t^2;**]
>> Remove[a];
>> ?f
>>
>> Global`f
>> f[b_]:=Module[{t},Removed[a][**t_]=b t^2;]
>>
>> What you have to do in your approach is to re-run the definition for "f",
>> to
>> be able to
>> use it. This is however pretty error-prone. You can cure this by calling
>> Clear or ClearAll
>> instead of Remove, but even this approach I don't consider a good
>> practice.
>> Even though
>> you use "a"  as a function, calling Clear or Remove on it means that in a
>> way, you use
>> it as a global variable. In this post:
>>
>> http://stackoverflow.com/**questions/6236458/plot-using-**
>> with-versus-plot-using-block-**mathematica/6236808#6236808<http://stackoverflow.com/questions/6236458/plot-using-with-versus-plot-using-block-mathematica/6236808#6236808>
>>
>> there is a lengthy discussion why making implicit dependencies on global
>> variables is a
>> bad practice.
>>
>> Here are a few ways out. What you seem to want is to generate a function
>> with embedded
>> parameters (a closure). One way is to generate a pure function and return
>> it:
>>
>> In[31]:= Clear[f];
>> f[b_]:=Function[t,b*t^2];
>> a = f[3];
>> a[t]
>> a=f[4];
>> a[t]
>> Remove[a];
>> a = f[5];
>> a[t]
>>
>> Out[34]= 3 t^2
>> Out[36]= 4 t^2
>> Out[39]= 5 t^2
>>
>> Another way is to explicitly pass to "f"  the symbol to which you want to
>> assign
>> the definition:
>>
>> In[40]:= Clear[ff,a];
>> ff[fname_Symbol,b_]:=Module[{**t},fname[t_]=b*t^2;];
>> ff[a,3];
>> a[t]
>> ff[a,4];
>> a[t]
>> Remove[a];
>> ff[a,5];
>> a[t]
>>
>> Out[43]= 3 t^2
>> Out[45]= 4 t^2
>> Out[48]= 5 t^2
>>
>> By making the function name an explicit parameter to "ff", you make the
>> problematic
>> situation above impossible to happen.
>>
>> HTH
>>
>> Regards,
>> Leonid
>>
>>
>>
>>
>>
>> On Thu, Jul 7, 2011 at 3:28 PM, blamm64 <blamm64 at charter.net> wrote:
>>
>>  This is what I get for querying SetDelayed
>>>
>>> In[1]:= ?SetDelayed
>>> lhs:=rhs assigns rhs to be the delayed value of lhs. rhs is maintained
>>> in an unevaluated form. When lhs appears, it is replaced by rhs,
>>> evaluated afresh each time.  >>
>>>
>>> Note particularly the above reads AFRESH EACH time.  It appears then
>>> the following is inconsistent behavior based on the above description:
>>>
>>> In[2]:= f[b_]:=Module[{t},a[t_]=b*t^2;**]
>>> In[3]:= a[t]
>>> Out[3]= a[t]
>>> In[4]:= f[3]
>>> In[5]:= a[t]//InputForm
>>> Out[5]//InputForm=
>>> 3*t^2
>>> In[6]:= f[5]
>>> In[7]:= a[t]//InputForm
>>> Out[7]//InputForm=
>>> 5*t^2
>>> In[8]:= Remove[a]
>>> In[9]:= f[4]
>>> In[10]:= a[t]//InputForm
>>> Out[10]//InputForm=
>>> a[t]
>>>
>>> Apparently AFRESH is not an accurate description of how SetDelayed
>>> operates in this case, or I am missing something about this particular
>>> interaction of Module, Remove, and global variables inside Modules.
>>>
>>> However, if I go back, after executing the last line above (<a> has
>>> been Removed), and place the cursor in the input line where <f> is
>>> defined and hit Enter, which I thought would be identical to just
>>> evaluating <f> AFRESH again, and then execute the <f[4]> line again,
>>> then the global <a> definition is re-constituted.
>>>
>>> The documentation for Remove reads the name is no longer recognized by
>>> Mathematica.  My understanding is that if the same name is defined
>>> AFRESH, it will once again be recognized.
>>>
>>> So if anyone would let me know what I am missing, regarding why the
>>> definition of <a> is not created AFRESH each time <f> is evaluated, I
>>> would appreciate it.
>>>
>>> Please don't construe the definition of <f> as my way of
>>> 'parameterizing' a function definition, I just use that definition to
>>> convey the apparent inconsistency.
>>>
>>> -Brian L.
>>>
>>>
>>>
>
> --
> DrMajorBob at yahoo.com
>


  • Prev by Date: Re: Interaction of Remove and Global variables in a Module
  • Next by Date: Re: Numerical accuracy/precision - this is a bug or a feature?
  • Previous by thread: Re: Interaction of Remove and Global variables in a Module
  • Next by thread: Re: Interaction of Remove and Global variables in a Module