我正在研究相当大的Mathematica项目,问题出现了我必须间歇性地检查数值结果,但希望能够轻松地恢复我的所有结构的分析形式。
代码相当流畅我不想在任何地方使用作用域构造,因为它们会增加工作开销。有没有一种简单的方法来识别和清除所有数字分配?
编辑:我确实知道确定范围是正确的方法;-)。但是,对于我的工作流程,我实际上只是在寻找一个肮脏的技巧,以便在事后确定所有数字赋值,而不是有先见之明来放下一个Block。答案 0 :(得分:2)
如果您的作业位于顶层,则可以使用以下内容:
a = 1;
b = c;
d = 3;
e = d + b;
Cases[DownValues[In],
HoldPattern[lhs_ = rhs_?NumericQ] |
HoldPattern[(lhs_ = rhs_?NumericQ;)] :> Unset[lhs],
3]
如果您有足够的历史记录长度$HistoryLength
(默认为无穷大),这将有效。但请注意,在上面的示例中,e
已分配3+c
,此处的3
未撤消。因此,问题在制定中确实含糊不清,因为有些数字可以使其成为定义。避免这种情况的一种方法是使用SetDelayed
进行分配,而不是使用Set
。
另一种选择是分析说Global'
上下文中的名称(如果这是您的符号所在的上下文),然后说出符号的OwnValues
和DownValues
,类似于上面的方式,并删除纯数字rhs的定义
但IMO这两种方法都不健全。我仍然使用范围构造并尝试隔离数字。一种可能性是在Block
中包装最终代码,并在此Block
内分配数值。这似乎是一种更清洁的方法。工作开销很小 - 您只需要记住要为其分配值的符号。 Block
会自动确保符号外没有定义。
修改强>
另一种可能性是使用当地规则。例如,可以定义rule[a] = a->1; rule[d]=d->3
而不是上面的分配。然后,您可以应用这些规则,如同提取它们一样
DownValues[rule][[All, 2]]
,只要你想用一些数字参数进行测试。
答案 1 :(得分:1)
在Andrew Moylan的solution的基础上,可以构建一个类似于Block的函数,它将采用规则:
SetAttributes[BlockRules, HoldRest]
BlockRules[rules_, expr_] :=
Block @@ Append[Apply[Set, Hold@rules, {2}], Unevaluated[expr]]
然后,您可以将数字规则保存在变量中,并使用BlockRules [savedrules,code],甚至可以定义一个应用固定规则集的函数,如下所示:
In[76]:= NumericCheck =
Function[body, BlockRules[{a -> 3, b -> 2`}, body], HoldAll];
In[78]:= a + b // NumericCheck
Out[78]= 5.
编辑为了回应Timo的评论,可以使用NotebookEvaluate(8中的新内容)来实现所请求的效果。
SetAttributes[BlockRules, HoldRest]
BlockRules[rules_, expr_] :=
Block @@ Append[Apply[Set, Hold@rules, {2}], Unevaluated[expr]]
nb = CreateDocument[{ExpressionCell[
Defer[Plot[Sin[a x], {x, 0, 2 Pi}]], "Input"],
ExpressionCell[Defer[Integrate[Sin[a x^2], {x, 0, 2 Pi}]],
"Input"]}];
BlockRules[{a -> 4}, NotebookEvaluate[nb, InsertResults -> "True"];]
作为此评估的结果,当本地设置为4时,您将获得一个评估您的命令的笔记本。为了更进一步,您将不得不拿笔记本
使用您的代码,打开一个新笔记本,评估Notebooks[]
以识别感兴趣的笔记本,然后执行:
BlockRules[variablerules,
NotebookEvaluate[NotebookPut[NotebookGet[nbobj]],
InsertResults -> "True"]]
我希望你能让这个想法奏效。