Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mathematica: How to clear the cache for a symbol, i.e. Unset pattern-free DownValues

Tags:

I'm a bad cacher: Sometimes, when no one is watching, I'll cache results without including the full context like so:

f[x_]:=f[x]=x+a; a=2; f[1]; DownValues[f]  Out[2]= {HoldPattern[f[1]]:>3,HoldPattern[f[x_]]:>(f[x]=x+a)} 

This leads to horribly subtle bugs, and, more importantly, to the need for clearing the cache when I change the context. One way of clearing the cache is to completely Clear the symbol and repeat the definitions, but this is not really a solution.

What I would really like is a method for clearing all pattern-free DownValues associated with a symbol.
For clarity, I'll include my present solution as an answer, but if fails on two counts

  • It only clears DownValues with all-numeric arguments
  • For aesthetical reasons, I'd like to avoid using Block to grab the DownValues.

Any ideas on how to improve ClearCache?

like image 657
Janus Avatar asked Feb 23 '11 03:02

Janus


2 Answers

I've made similar functions in the past (but I can't remember where).

Does the following code do all that you need?

ClearCache[f_] := DownValues[f] = DeleteCases[DownValues[f],                                                _?(FreeQ[First[#], Pattern] &)] 

This maybe should be extended to UpValues and SubValues. And the Head of f restricted to Symbol.

like image 188
Simon Avatar answered Sep 29 '22 02:09

Simon


Just to complement the other excellent solution: if you have a very large list of DownValues and have strict efficiency requirements for ClearCache, you can significantly speed up the process by clearing all definitions and then reconstructing only those with patterns. Here is an example:

In[1]:=  ClearCache[f_] :=    DownValues[f] = DeleteCases[DownValues[f], _?(FreeQ[First[#], Pattern] &)];  In[2]:= Clear[f]; f[x_] := f[x] = x;  In[4]:= f /@ Range[1000000];  In[5]:= ClearCache[f]; // Timing  Out[5]= {7.765, Null}  In[6]:=  ClearAll[createDefs]; SetAttributes[createDefs, HoldRest]; createDefs[f_, defs_: Automatic] :=         (createDefs[f] := (Clear[f]; defs); createDefs[f]);  In[9]:= Clear[f]; createDefs[f, f[x_] := f[x] = x]  In[11]:= f /@ Range[1000000];  In[12]:= Length[DownValues[f]]  Out[12]= 1000001  In[13]:= createDefs[f]; // Timing  Out[13]= {1.079, Null}  In[14]:= DownValues[f]  Out[14]= {HoldPattern[f[x_]] :> (f[x] = x)} 

Note that you only have to call the createDefs once with the code that creates the pattern-based definitions of the function. All other times, you call it as createDefs[f], because it memoizes the code needed to re-create the definitions, on the first call.

It is also possible that you don't want to grow huge caches, but this is out of your control in the simple f[x_]:=f[x]=rhs approach. In other words, the cache may contain lots of unnecessary old stuff, but in this approach you can not tell old (no longer used) definitions from the new ones. I partially addressed this problem with a package I called Cache, which can be found here together with the notebook illustrating its use. It gives you more control over the size of the cache. It has its problems, but may occasionally be useful.

like image 28
Leonid Shifrin Avatar answered Sep 29 '22 01:09

Leonid Shifrin