Wolfram mathematica 如何获取与其他符号关联的所有定义?
如何通过Wolfram mathematica 如何获取与其他符号关联的所有定义?,wolfram-mathematica,Wolfram Mathematica,如何通过TagSet、TagSetDelayed、UpSet或UpSetDelayed>获取与其他符号关联的符号的所有定义 例如,如果已定义 area[square] ^= s^2 area[cube] ^= 6*s^2 如何获得这些定义,不知道名称正方形,立方体,只知道名称区域 我刚刚发现UpValues没有返回makebox和N的定义,因为它们存储在FormatValues和NValues中: In[1]:= rotate /: MakeBoxes[expr_rotate, "Stand
TagSet
、TagSetDelayed
、UpSet
或UpSetDelayed>获取与其他符号关联的符号的所有定义
例如,如果已定义
area[square] ^= s^2
area[cube] ^= 6*s^2
如何获得这些定义,不知道名称正方形
,立方体
,只知道名称区域
我刚刚发现UpValues
没有返回makebox
和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
列表时,可能会遇到makebox
的问题,因为FormatValues
给出了makebox
的定义。可以通过将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, _]]}}]}
您可以尝试通过
Select[UpValues /@ Cases[ToExpression[Names["*"]], _Symbol], ! FreeQ[#, area] &]
在你的例子中会产生什么
{{HoldPattern[area[cube]] :> 6 s^2}, {HoldPattern[area[square]] :> s^2}}
为了解决Alexey对Howard答案的担忧,我提出了以下建议:
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] &]
]
]
以下版本
Cases[
Flatten@Map[
ToExpression[#, InputForm, Function[sym, UpValues[sym], HoldAllComplete]] &,
Names["Global`*"]],
Verbatim[RuleDelayed][Verbatim[HoldPattern][_area], _]
]
也不会计算符号。它在精神上与@Mr.Wizard的答案类似,但我更喜欢ToExpression
而不是MakeExpression
,因为后者绑定到前端和框(至少在概念上是这样),而前者是一个通用命令(尽管文档中提到它将使用MakeExpression
的规则)
如果您从一开始就可以访问完整的Mathematica会话,另一种解决方案是重载标记集
、标记集延迟
、翻转
和翻转
,以便它们将符号依赖项记录在某种散列中。下面是心烦意乱的一个例子:
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];
在此重新定义后,所有使用打乱的完成的作业都将被记录。例如,在执行上面的示例之后,您可以调用
In[6]:= getUpsetHash[][area]
Out[6]= {HoldComplete[square], HoldComplete[cube]}
通过这种方式,您可以更快地获取信息,尤其是如果您希望经常进行此类查询,并且/或者您已经加载了大量软件包。您还可以进一步自动化该过程,以便在加载感兴趣的功能后切换到工作分配的标准定义。此代码是危险的,因为$ContextPath
中的每个符号都经过计算!应该有一种方法可以做到这一点,而不需要对符号进行评估。另一个问题是,此代码还将返回在r.h.s.或l.h.s.上具有square
的定义,但不在HoldPattern
内子表达式的Head
位置。不过还是要谢谢你。我不明白你反对发表意见,但我已经学会了在你讲话时倾听。你能进一步解释一下吗?另外,为什么需要函数[sym,UpValues[sym],HoldAllComplete]
?@Mr.Wizard该函数用于将的输出包装到表达式
,而不进行计算<默认情况下,在对其求值之前,code>MakeExpression将其输出包装在HoldComplete
中。顺便说一句,我认为在这种特殊情况下,HoldFirst
属性就足够了。ToExpression
当第二个参数是StandardForm
或TraditionalForm
时,只调用MakeExpression
:在[MakeExpression]上尝试;表达[“1+1”,标准格式]
。但是对于InputForm
它不支持,因为MakeExpression
不支持InputForm
作为第二个参数。作为比较,ToBoxes
总是调用makebox
@Mr.Wizard这并不是一个真正的反对意见-我只是提到我更喜欢来表达
。至于UpValues
,你可能也是对的,HoldAllComplete
是一种过分的杀伤力(我刚刚在ToExpression
中习惯了这种模式,对于那些不包含参数的函数,它们也需要一个Unevaluated
)。我的主要观点是我回答的第二部分,对于第一部分,我只是展示了一个对我来说更自然的选择(但这当然是非常主观的)。所以,在这个特殊的案例中,你不会因为不听我的话而损失太多:)@Alexey这是一个没有文件证明的表格,但我相信你可以信赖它。对它的支持不太可能停止。而且,据我所知,这是唯一一种引入具有任意数量变量的纯函数的方法,这些变量将被持有(或携带其他属性)。请看我的这篇文章作为一个例子,在文章的最后我提到了这个表单的位置。我认为这个解决方案非常优雅!您和@Leonid的解决方案都评估区域
。可以通过使用HoldPattern
来避免这种情况:HoldPattern[area][\u]
。在此之后,代码变得几乎安全。唯一危险的情况是定义区域[惊喜]^:=未评估[评估[打印[“惊喜]:)“]]]
。在这种非常特殊的情况下,两个版本都评估定义。但我认为我们不应该通常关心这些黑客的异国情调。@Alexey,area
什么时候会有价值?如果我分配area[square]^=s^2
然后area=5
,然后计算area[square]
我得到5[square]
@Alexey,以你的例子来说,如果在一个新内核中计算,我不会得到“!”打印:area[square]^=s^2;area:=(Print[“!”];area=;area)Cases[UpValues@@@MakeExpression/@Names[“Global`*]、HoldPattern[\uuuuuu area:>\uu]、{2}]
@Mr