18
$\begingroup$

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.

$\endgroup$

1 Answer 1

22
$\begingroup$

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.

$\endgroup$
3
  • 1
    $\begingroup$ Using OwnValues as suggested has one possible drawback: it would select, among other entities, a symbol defined to be a pure function. $\endgroup$
    – murray
    Sep 27, 2012 at 15:05
  • $\begingroup$ @murray That the symbol contains a value that happens to be a pure function does not make that symbol be not a variable. Rather, it confirms that Mathematica is a functional language (or, rather, an emulation, but often we don't have to make a difference), where functions are values, as well as other types. Only my opinion, of course. And I agree with you that this creates an ambiguity in the question, but then the question itself has to be better formulated to cover this case. $\endgroup$ Sep 27, 2012 at 16:12
  • 1
    $\begingroup$ @murray Actually, I really agree with you that the type of automation provided by the first method may be too dangerous since it takes a rather cavalier approach towards variable clearing. This was the whole reason why I described the second one, where you have a choice to not wrap defVar around an assignment if you don't want to treat the symbol there as a variable. $\endgroup$ Sep 27, 2012 at 16:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.