Is there any harm or benefit to Removing unneeded private symbols in packages?

I decided to take one of my large packages and Remove all symbols in the Private` context that have no definitions attached to them

...

And is there any risk if only those symbols that are not used globally or that do not have definitions are carefully removed?

In general, the complexity of the Mathematica language and the intricacies of the evaluation sequence, which are not entirely understood even by people very comfortable with Mathematica (myself included) makes it very hard to identify or predict with certainty what symbols don't have any definitions (currently) and will never have any definitions (in the future) attached to them.

As a simple example:

BeginPackage["Example`"]

ClearAll@F;
ClearAll@G;

Begin["`Private`"]

ClearAll@f;
f[x_] := (a := 1;True) /; x > 2
f[x_] := False

F[x_] := f[x^2]
G[x_] := Symbol[x] > 0    

End[]
EndPackage[]

If you load the package, Example`Private`a has no definitions associated with it and is used nowhere else "globally", so it could be removed according to your definition. Yet, if you evaluate the following:

F[5];
G["Example`Private`a"]

one would expect the result to be True, but it would simply be Example`Private`a in your case.

You shouldn't be worrying about "unnecessary" symbols in a hidden context that you are never exposed to. Truly unnecessary symbols may be bad style, but that's on the author of the package, not you. Perhaps the complexity of the package/algorithm might necessitate these extra symbols just to reduce the cognitive overhead of interpreting obscure/terse/fancy point-free style coding 2 years later when you're debugging. Sometimes it might also be a reflection of the author's own personal familiarity/comfort with the language at the time the package was written. In short, these aren't really issues that cause any discomfort to the user of the package.

Instead, what you should be focusing on are performance issues like

  • Do any of the "unnecessary" symbols in the package's private context leak memory?
  • Are any of the symbols in the private context getting exposed accidentally in other contexts?

etc. Those are issues worth investigating and fixing, as they have the potential to cause issues downstream for the users of the package.


As a more direct answer to the question of memory we can check with a test.

In[1]:= MemoryInUse[]

(* Out[1]= 34093104 *)

In[2]:= bunchOfSymbols = Table[Unique[], {26000}];

In[3]:= foo[Sequence @@ bunchOfSymbols] := bar;

In[4]:= MemoryInUse[]

(* Out[4]= 43032256 *)

In[5]:= Remove @@ bunchOfSymbols;

In[6]:= MemoryInUse[]

(* Out[6]= 41577200 *)

This indicates that (in version 10.1 under Windows x64) Removing a Symbol saves only about 56 bytes of memory which seems inconsequential by itself unless one has a truly excessive number of Symbols.

Also I noticed in this test that the Remove step caused temporary freeze in my Front End though I could not capture it with Timing, AbsoluteTiming, etc. This could make loading your package annoying for others if it is distributed. The freeze gets longer when the number of Symbols removed increases, therefore in any case where significant memory would be recovered the freeze would be problematic.