如何通过TagSet
,TagSetDelayed
,UpSet
或UpSetDelayed
获取与其他符号关联的符号的所有定义?
例如,如果已经定义了
area[square] ^= s^2
area[cube] ^= 6*s^2
如何获取这些定义,不知道名称square
,cube
,但只知道名称area
?
我刚发现UpValues
没有返回MakeBoxes
和N
的定义,因为它们相应地存储在FormatValues
和NValues
中:
In[1]:= rotate /: MakeBoxes[expr_rotate, "StandardForm"] := x
UpValues[rotate]
FormatValues[rotate]
Out[2]= {}
Out[3]= {HoldPattern[MakeBoxes[expr_rotate, "StandardForm"]] :> x}
In[4]:= pi /: N[pi] = 3.14
UpValues[pi]
NValues[pi]
Out[4]= 3.14
Out[5]= {}
Out[6]= {HoldPattern[N[pi, {MachinePrecision, MachinePrecision}]] :>
3.14}
以这种方式而不是UpValues
,我们应该使用UpValues
,FormatValues
和NValues
的组合。
当尝试输出FormatValues
列表时,MakeBoxes
可能会遇到问题,因为FormatValues
会为MakeBoxes
FormatType
提供OutputForm
的定义。通过暂时将In[1]:= SetOptions[$Output,FormatType->OutputForm];
FormatValues[DialogNotebook]
Out[2]= {HoldPattern[MakeBoxes[BoxForm`apat$:HoldPattern[DialogNotebook[___]], BoxForm`fpat$_]] :>
BoxForm`BoxFormAutoLoad[MakeBoxes, BoxForm`apat$, BoxForm`fpat$, Typeset`CellNotebook`,
{{CellGroup, _}, {DocumentNotebook, _}, {PaletteNotebook, _}, {DialogNotebook, _}, {ExpressionCell, _}, {Text, _},
{TextCell, _}, {Cell, HoldPattern[MakeExpression[_Cell, _]]}, {Notebook, HoldPattern[MakeExpression[_Notebook, _]]}}]}
In[1]:= ToString@FormatValues[DialogNotebook]
Out[1]= {HoldPattern[MakeBoxes[BoxForm`apat$:HoldPattern[DialogNotebook[___]], BoxForm`fpat$_]] :> BoxForm`BoxFormAutoLoad[MakeBoxes, BoxForm`apat$, BoxForm`fpat$, Typeset`CellNotebook`, {{CellGroup, _}, {DocumentNotebook, _}, {PaletteNotebook, _}, {DialogNotebook, _}, {ExpressionCell, _}, {Text, _}, {TextCell, _}, {Cell, HoldPattern[MakeExpression[_Cell, _]]}, {Notebook, HoldPattern[MakeExpression[_Notebook, _]]}}]}
切换为{{1}}或将这些定义转换为字符串,可以解决此问题。
{{1}}
答案 0 :(得分:4)
试图解决阿列克谢对霍华德答案的担忧,我想出了这个:
Cases[
UpValues @@@ MakeExpression /@ Names["Global`*"],
HoldPattern[_@_area :> _],
{2}
]
根据您的更新要求,以下是高级版本:
SetAttributes[otherValues, HoldFirst]
otherValues[sym_] :=
With[{names = MakeExpression /@ Names["Global`*"]},
Join[
Cases[UpValues @@@ names, HoldPattern[_@_sym :> _], {2}],
Cases[NValues @@@ names, HoldPattern[_@N[sym, ___] :> _], {2}],
Select[Join @@ FormatValues @@@ names, ! FreeQ[#, HoldPattern@sym] &]
]
]
答案 1 :(得分:3)
您可以尝试通过
进行详尽的搜索Select[UpValues /@ Cases[ToExpression[Names["*"]], _Symbol], ! FreeQ[#, area] &]
在你的例子中将产生
{{HoldPattern[area[cube]] :> 6 s^2}, {HoldPattern[area[square]] :> s^2}}
答案 2 :(得分:3)
以下版本
Cases[
Flatten@Map[
ToExpression[#, InputForm, Function[sym, UpValues[sym], HoldAllComplete]] &,
Names["Global`*"]],
Verbatim[RuleDelayed][Verbatim[HoldPattern][_area], _]
]
也不会评估符号。它与@Mr的精神相似。向导的回答,但我更喜欢ToExpression
到MakeExpression
,因为后者与FrontEnd和框(至少在概念上)相关联,而前者是一个通用命令(尽管文档中提到了它)它将使用MakeExpression
的规则。
如果您从一开始就可以访问完整的Mathematica会话,则另一种解决方案是重载TagSet
,TagSetDelayed
,UpSet
和UpSetDelayed
,以便他们能够在某种哈希中记录符号依赖关系。以下是UpSet
的示例:
Unprotect[UpSet];
Module[{tried, upsetHash},
upsetHash[_] = {};
getUpsetHash[] := upsetHash;
UpSet[f_[args___], rhs_] :=
Block[{tried = True},
AppendTo[upsetHash[f],
Select[HoldComplete[args],
Function[Null, Head[Unevaluated[#]] === Symbol, HoldAll]]];
UpSet[f[args], rhs]] /; ! TrueQ[tried]
];
Protect[UpSet];
将记录此重新定义后使用UpSet
进行的所有分配。例如,在执行上面的示例后,您可以调用
In[6]:= getUpsetHash[][area]
Out[6]= {HoldComplete[square], HoldComplete[cube]}
通过这种方式,您可以更快地获取信息,特别是如果您想经常进行此类查询,并且/或者您加载了大量软件包。您还可以进一步自动化该过程,在加载感兴趣的功能后切换到分配的标准定义。