How to get all definitions associated with other symbols?
How to get all definitions for a symbol associated with other symbols by TagSet
, TagSetDelayed
, UpSet
or UpSetDelayed
?
For example, if one has defined
area[square] ^= s^2
area[cube] ^= 6*s^2
how to obtain these definitions, not knowing the names square
, cube
but knowing only the name area
?
I just have found that UpValues
does not return definitions for MakeBoxes
and N
since they are stored in FormatValues
and NValues
correspondingly:
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}
In this way instead of UpValues
we should use a combination of UpValues
, FormatValues
and NValues
.
When trying to output a list of FormatValues
one can face problems with MakeBoxes
since FormatValues
gives definitions for MakeBoxes
those are further processed by MakeBoxes
on creating the output for the FrontEnd. This problem can be solved by switching FormatType
temporarily to OutputForm
or by converting these definitions to strings.
In[1]:= SetOptions[$Output,FormatType->OutputForm];
FormatValues[DialogNotebook]
Out[2]= {HoldPattern[MakeBoxes[BoxForm`apat$:HoldP开发者_开发知识库attern[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, _]]}}]}
Attempting to address Alexey's concerns with Howard's answer, I came up with this:
Cases[
UpValues @@@ MakeExpression /@ Names["Global`*"],
HoldPattern[_@_area :> _],
{2}
]
In response to your updated requirements, here is the advanced version:
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] &]
]
]
You can try an exhaustive search via
Select[UpValues /@ Cases[ToExpression[Names["*"]], _Symbol], ! FreeQ[#, area] &]
which in your example will yield
{{HoldPattern[area[cube]] :> 6 s^2}, {HoldPattern[area[square]] :> s^2}}
The following version
Cases[
Flatten@Map[
ToExpression[#, InputForm, Function[sym, UpValues[sym], HoldAllComplete]] &,
Names["Global`*"]],
Verbatim[RuleDelayed][Verbatim[HoldPattern][_area], _]
]
will not evaluate symbols as well. It is similar in spirit to @Mr. Wizard's answer, but I prefer ToExpression
to MakeExpression
since the latter is tied to the FrontEnd and boxes ( at least conceptually) , while the former is a general-purpose command (although it is mentioned in the documentation that it will use rules for MakeExpression
).
If you have an access to the full Mathematica session from the start, another solution would be to overload TagSet
, TagSetDelayed
, UpSet
and UpSetDelayed
so that they will record the symbol dependencies in some kind of hash. Here is an example for 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];
All assignments made with UpSet
after this redefinition will be recorded. For example, after executing your example above, you can call
In[6]:= getUpsetHash[][area]
Out[6]= {HoldComplete[square], HoldComplete[cube]}
This way you get your information much faster, especially if you want to make such inquiries frequently, and/or you have lots of packages loaded. You can also automate the process further, to switch to the standard definitions for assignments once you load the functionality of interest.
精彩评论