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
Block
to grab the DownValues.Any ideas on how to improve ClearCache
?
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
.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With