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