Wolfram mathematica Mathematica:如何清除符号的缓存,即未设置模式自由值
我是一个糟糕的缓存器:有时,当没有人观看时,我会缓存结果,但不包括完整的上下文,如下所示:Wolfram mathematica Mathematica:如何清除符号的缓存,即未设置模式自由值,wolfram-mathematica,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)} 这导致了极其微妙的bug,更重要的是,当我更改上下文时需要清除缓存。清除缓存的一种方法是完全清除符号并重复定义,但这并不是真正的解决方案 我真正想要的是一种清除与符号关联的所有无模式下
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)}
这导致了极其微妙的bug,更重要的是,当我更改上下文时需要清除缓存。清除缓存的一种方法是完全清除
符号并重复定义,但这并不是真正的解决方案
我真正想要的是一种清除与符号关联的所有无模式下行值的方法。为了清楚起见,我将包括我目前的解决方案作为一个答案,但如果在两个方面失败了
- 它只清除带有所有数值参数的DownValue
- 出于美观的原因,我希望避免使用
来获取下行值Block
关于如何改进
ClearCache
有什么想法吗?这是我目前针对这个问题的解决方案,但正如问题中提到的,它不是严格地寻找无模式的DownValues
,也不是很优雅。为
f
In[6]:= dv = DownValues[f]
Out[6]= {HoldPattern[f[1]] :> 3, HoldPattern[f[x_]] :> (f[x] = x + a)}
查找DownValues
以清除块中的内容
,避免立即计算
In[7]:= dv2clear = Block[{f},
Hold@Evaluate@Cases[dv,
HoldPattern[f[args__ /; Apply[And, NumericQ /@ Flatten[{args}]]]], {3}]]
Out[7]= Hold[{f[1]}]
将Unset
应用于保留列表中的目标DownValues
,然后释放
In[8]:= Map[Unset, dv2clear, {2}]
ReleaseHold@%
Out[8]= Hold[{(f[1]) =.}]
这个很好用
In[10]:= DownValues[f]
Out[10]= {HoldPattern[f[x_]] :> (f[x] = x + a)}
可以这样包装:
ClearCache[f_] := Module[{dv, dv2clear},
(* Cache downvalues for use inside block *)
dv = DownValues[f];
(* Find the downvalues to clear in Block to avoid immediate evaluation *)
dv2clear = Block[{f},Hold@Evaluate@Cases[dv,HoldPattern[
f[args__ /; Apply[And, NumericQ /@ Flatten[{args}]]]], {3}]];
(* Apply Unset to the terms inside the held list and then release *)
ReleaseHold@Map[Unset, dv2clear, {2}];]
我以前也做过类似的函数(但我不记得在哪里) 下面的代码是否满足了您的所有需要
ClearCache[f_] := DownValues[f] = DeleteCases[DownValues[f],
_?(FreeQ[First[#], Pattern] &)]
这可能应该扩展到
UpValues
和SubValues
。而f
的头
仅限于符号
只是为了补充另一个优秀的解决方案:如果您有一个非常大的下行值列表
,并且对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)}
请注意,您只需使用创建基于模式的函数定义的代码调用一次createDefs
。所有其他时间,您都将其称为createDefs[f]
,因为它在第一次调用时会记住重新创建定义所需的代码
也有可能您不想增加巨大的缓存,但这在简单的
f[x]:=f[x]=rhs
方法中是无法控制的。换句话说,缓存可能包含许多不必要的旧内容,但在这种方法中,您无法区分旧(不再使用)定义和新定义。我用一个名为Cache的包部分地解决了这个问题,这个包可以和说明其用法的笔记本一起找到。它使您能够更好地控制缓存的大小。它有它的问题,但有时可能有用 一旦我实施了一个计划(并保存内存)。在该页上搜索备忘录。这在这里可能也很有用(特别是考虑到一些标记为重复的问题)
代码
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] =. )
用法和说明
此版本适用于采用单个数值参数的函数。调用
memo[f][x]
而不是f[x]
来使用记忆版本。缓存的值仍然与f
关联,因此当清除f
时,它们就消失了。默认情况下,缓存值的数量限制为200。使用memoClearCache[f]
清除所有已记忆的值。@belisarius:你没有投票权的评论让我怀疑我做了什么蠢事。。。一个简单的解决方案并不意味着我是个傻瓜,是吗?@Simon我只是忘了投票。我真丢脸!那图案真漂亮。哇!这看起来和我想做的一模一样。有一点技术上的问题可以让问题多讨论几分钟:你取消了向下值清除的资格,即使它在RHS上只有一个模式——对于ClearCache Nirvana,我们可能应该只看LHS。@Janus:幸运的是,这很容易修复-请参阅编辑。(顺便说一句,涅磐?你一定非常想要这个ClearCache
功能!)谢谢西蒙!我会让它开几个小时——因为在我还没看到它之前,当一个问题就结束时,它总是让我恼火:)谢谢,莱昂尼德。这里也列出了这种方法,这很好。我偶尔会使用它(即在构建“ClearCache”之前),但我并不喜欢它如何干扰实现过程。对于我的特殊用途,我缓存的结果非常昂贵,以至于我可以在一眨眼之间清除一年的缓存:)