Mathematica:如何清除符号的缓存,即Unset pattern-free DownValues

Jan*_*nus 22 wolfram-mathematica

我是一个糟糕的人:有时,当没有人在观看时,我会缓存结果而不包括完整的上下文,如下所示:

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)}
Run Code Online (Sandbox Code Playgroud)

这会导致可怕的细微错误,更重要的是,当我更改上下文时需要清除缓存.清除缓存的一种方法是完全Clear符号并重复定义,但这不是一个真正的解决方案.

我真正想要的是一种清除与符号相关的所有无模式DownValues的方法.
为清楚起见,我将把我目前的解决方案作为答案包括在内,但如果两个方面都失败了

  • 它只使用全数字参数清除DownValues
  • 出于美学原因,我想避免使用Block抓住DownValues.

关于如何改进的任何想法ClearCache

Sim*_*mon 24

我过去曾做过类似的功能(但我不记得在哪里).

以下代码是否满足您的所有需求?

ClearCache[f_] := DownValues[f] = DeleteCases[DownValues[f], 
                                              _?(FreeQ[First[#], Pattern] &)]
Run Code Online (Sandbox Code Playgroud)

这可能应该扩展到UpValuesSubValues.和Headf限制为Symbol.

  • 谢谢西蒙!我会把它打开几个小时 - 只是因为在我看到它之前关闭一个问题时它总是让我烦恼:) (3认同)

Leo*_*rin 8

只是为了补充其他优秀的解决方案:如果您有一个非常大的列表DownValues并且具有严格的效率要求ClearCache,则可以通过清除所有定义然后仅重建具有模式的定义来显着加快流程.这是一个例子:

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)}
Run Code Online (Sandbox Code Playgroud)

请注意,您只需createDefs使用创建函数基于模式的定义的代码调用一次.所有其他时间,您将其称为createDefs[f],因为它会在第一次调用时记住重新创建定义所需的代码.

您也可能不希望增加巨大的缓存,但这在简单的f[x_]:=f[x]=rhs方法中是您无法控制的.换句话说,缓存可能包含许多不必要的旧东西,但在这种方法中,您无法告诉新的(不再使用的)旧定义.我用一个名为Cache的软件包部分解决了这个问题,可以在这里找到说明它的用途的笔记本.它使您可以更好地控制缓存的大小.它有它的问题,但偶尔也可能有用.


Sza*_*lcs 6

一旦我实现了一个方案来限制memoized值的数量(并节省内存).在该页面上搜索memoization.这在这里也许有用(特别是考虑到一些标记为重复的问题).

代码

SetAttributes[memo, HoldAll]
SetAttributes[memoStore, HoldFirst]
SetAttributes[memoVals, HoldFirst]

memoVals[_] = {};

memoStore[f_, x_] := 
 With[{vals = memoVals[f]}, 
  If[Length[vals] > 200, 
   f /: memoStore[f, First[vals]] =.;
   memoVals[f] ^= Append[Rest[memoVals[f]], x], 
   memoVals[f] ^= Append[memoVals[f], x]];
  f /: memoStore[f, x] = f[x]]

memo[f_Symbol][x_?NumericQ] := memoStore[f, x]

memoClearCache[f_Symbol] := 
 (Scan[(f /: memoStore[f, #] =.) &, memoVals[f]]; 
  f /: memoVals[f] =. )
Run Code Online (Sandbox Code Playgroud)

用法和描述

此版本适用于采用单个数字参数的函数.调用memo[f][x]而不是f[x]使用memoized版本.缓存的值仍然与之关联f,因此f清除后,它们就会消失.默认情况下,缓存值的数量限制为200.使用memoClearCache[f]清除所有memoized值.