Как получить все определения, связанные с другими символами? - PullRequest
5 голосов
/ 30 апреля 2011

Как получить все определения для символа, связанного с другими символами 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, эти дополнительно обрабатываются MakeBoxes при создании вывода для FrontEnd . Эту проблему можно решить, временно переключив 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, _]]}}]}

Ответы [ 3 ]

4 голосов
/ 30 апреля 2011

Пытаясь ответить на вопросы Алексея с помощью ответа Говарда, я придумал следующее:

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] &]
    ]
  ]
3 голосов
/ 30 апреля 2011

Следующая версия

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]} 

Таким образом, вы получите свою информацию намного быстрее, особенно если вы хотите часто делать такие запросы, и / или у вас загружено много пакетов.Вы также можете дополнительно автоматизировать процесс, чтобы перейти к стандартным определениям для назначений после загрузки интересующей вас функциональности.

3 голосов
/ 30 апреля 2011

Вы можете попробовать исчерпывающий поиск через

Select[UpValues /@ Cases[ToExpression[Names["*"]], _Symbol], ! FreeQ[#, area] &]

, который в вашем примере даст

{{HoldPattern[area[cube]] :> 6 s^2}, {HoldPattern[area[square]] :> s^2}}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...