TransWikia.com

Is it possible to Clear all variables (but not functions)?

Mathematica Asked on February 11, 2021

I have written a Mathematica script in which I define functions and variables. Here is a vastly simplified example:

myFunA[int_Integer] := int + 1
myFunB[int_Integer] := int * 2
myFunC[int_Integer] := int - 3

myVarA = 1;
myVarB = 2;
myVarC = 3;

(In my actual script, the function and variable names vary; they do not follow the form myFunX, myVarX, etc.)

I would like to Clear (or otherwise delete) all of the variables (myVarA, myVarB, myVarC) but not the functions (myFunA, myFunB, myFunC). Is this possible (without explicitly Clearing each of the many variables, since my actual script defines several dozen variables)? Thank you for your time.

One Answer

Automatic way based on Names

Here is a simple modification of the recent answer of @R.M, which is based on the definiton of a variable as a symbol which has an OwnValue defined:

Clear @@ 
   Select[
      Names["Global`*"], 
      ToExpression[#, StandardForm, 
         Function[sym, OwnValues[sym] =!= {}, HoldAll]
      ] &
   ]

If your code is in some context other than Global` (which is what I'd recommend), you can put that context in place of Global` above.

Automation based on custom assignment operator

As an alternative, and IMO more systematic way, you may define a custom assignment operator which you'd use when defining a variable:

ClearAll[defVar, $variables, clearVars];

$variables = Hold[];

SetAttributes[defVar, HoldAll];
defVar[def : ((Set | SetDelayed)[lhs_Symbol, rhs_])] :=
  With[{result = def},
    $variables = Append[$variables, Unevaluated[lhs]];
    result];

clearVars[] := $variables /. Hold[vars__] :> Clear[vars];

Now, you use this as

myFunA[int_Integer] := int + 1
myFunB[int_Integer] := int*2
myFunC[int_Integer] := int - 3

defVar[myVarA = 1];
defVar[myVarB = 2];
defVar[myVarC = 3];

And then,

clearVars[]

A digression: evaluation leak in AppendTo

Interestingly, in the line $variables = Append[$variables, Unevaluated[lhs]], you can not use AppendTo instead, at least not in the form one would expect it to work. The reason is rather subtle: AppendTo seems to be implemented in the top-level code, but more importantly, it leaks evaluation:

vars = vars1 = Hold[];
a=1;
AppendTo[vars,Unevaluated[a]];
AppendTo[vars1,Unevaluated@Unevaluated[a]];
{vars,vars1}

(* {Hold[1],Hold[a]} *)

You see that an extra layer of Unevaluated is necessary to counter the evaluation leak. I would think this is a wrong behavior for AppendTo, but can not state with definiteness that this is a bug.

Remarks

Which way to choose depends on the situation. The first method is fully automatic and will work best if you keep all your work in a specific context distinct from Global`. The second way requires more discipline but works regardless of the contexts you are using.

Answered by Leonid Shifrin on February 11, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP