Оцените вне одного уровня в Хранении в Mathematica

mathematica документация относительно Оценивает в возможных проблемах, говорит:

Оцените работы только на первом уровне, непосредственно в сохраненной функции

Почему Mathematica имеет это ограничение? Таким образом, если у меня есть выражение больше чем с одним уровнем, берут этот упрощенный пример:

Держите [Плюс [Плюс [2, 2], 2]]]

Теперь предположите, что я хочу видеть то, что ответ к второе Плюс, ничего не оценивая на уровнях ниже его. Я попробовал разные вещи, такие как:

In[290]:= Hold[Plus[Evaluate[Plus[2, 2]], 2]]
Out[290]= Hold[Evaluate[2+2]+2]

In[287]:= Hold[Plus[ReleaseHold[Hold[Plus[2, 2]]], 2]]
Out[287]= Hold[ReleaseHold[Hold[2+2]]+2]

Первое Хранение сохраняет все неоцененным в и вне первого уровня в этом случае. Цель состоит в том, чтобы управлять оценкой выражения на каждом этапе от самой внутренней вложенной функции до внешней с помощью последовательного Хранения, ReleaseHold и Оценить функции для достижения этого. Я знаю, что мог использовать трассировку для наблюдения то, что происходит вне уровня один в выражении, но это отличается и иногда сложно для чтения с более длительными выражениями.

Кажется, что единственный путь состоит в том, чтобы извлечь и полностью отменить выражение в списки с помощью Извлечения, Части или Уровня; оцените часть выражения, которое я хочу; затем восстановите и повторно отобразите выражение назад вместе для каждого этапа. Есть ли какие-либо другие подходы или функции для достижения этого, я мог рассмотреть?

Править: Это могло бы быть лучшим примером для рассмотрения подхода выпуска первого хранения. С выражением:

Hold[Plus[Plus[2, Plus[2,2]], 2]]]

Если Вы выпускаете первое хранение и помещаете хранение над более высоким уровнем в выражении в третьем Плюс, для сходства с этим:

in = Plus[Plus[2, Hold[Plus[2,2]]], 2]]]
out = Hold[2+2]+4

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

8
задан Kara 26 June 2014 в 19:16
поделиться

3 ответа

Я не могу назвать точную причину, почему Evaluate «работает только на первом уровне, непосредственно внутри удерживаемой функции», но я подозреваю, что это частично эффективность, так как был бы медленным, если бы оценщику пришлось сканировать полное дерево выражений удерживаемых аргументов, переданных в любую функцию с атрибутом Hold * для вложенных Вычислить выражения и оценить их, а затем выполнить рекурсию и просмотреть for Оценивать подвыражения в том, что они только что вычислили, при этом оставив остальную часть выражения невычисленной, особенно если это не всегда может быть тем, что вы хотите в любом случае.

Делать то, что вы хотите, довольно легко, используя комбинацию Extract и ReplacePart , хотя:

In[51]:= expr = Hold[Plus[Plus[2, 2], 2]];

In[52]:= ReleaseHoldAt[expr_, partspec_] :=
  ReplacePart[expr, partspec -> Extract[expr, partspec]]

In[53]:= ReleaseHoldAt[expr, {1, 1}]

Out[53]= Hold[4 + 2]

Это позволяет нам проиллюстрировать еще одну причину, по которой это может не иметь смысла для Оцените для работы на любом уровне в выражении, переданном в качестве аргумента функции с атрибутом Hold * , учитывая следующее выражение, включающее i :

In[82]:= i = 1;

In[83]:= ReleaseHoldAt[Hold[i = 2; j = Plus[i, i]], {1, 2}]

Out[83]= Hold[i = 2; 2]

Обратите внимание, что значение j было бы 4 , если бы мы оценили первую часть этого выражения до Plus , но результаты отличаются, поскольку мы выполняем только частичные оценка, и i = 2 не оценивались, когда мы оценивали настройку подвыражения j . Иногда это может быть то, что вы хотите, но часто это не так.

Помните, что даже Evaluate на первом уровне можно обойти с помощью функции с атрибутом HoldAllComplete или с помощью HoldComplete :

In[62]:= Hold[Evaluate[Plus[2,2]]]
Out[62]= Hold[4]

... против:

In[63]:= HoldComplete[Evaluate[Plus[2,2]]]
Out[63]= HoldComplete[Evaluate[2+2]]

Наконец, вывод Trace может быть немного плотным, но вы можете отфильтровать то, что хотите, используя шаблоны или символы, представляющие интерес во втором аргументе:

In[88]:= Trace[Plus[Plus[Plus[1,2],3],4],Plus]
Out[88]= {{{1+2,3},3+3,6},6+4,10}

In[93]:= Trace[Plus[Subtract[Plus[1,2],4],8],_Plus]
Out[93]= {{{1+2}},-1+8}

HTH !

3
ответ дан 5 December 2019 в 17:34
поделиться

Техника, которая не включает Extract- это обернуть части внутри Hold во внутренние Holdы, а затем отпустить внешний Hold:

expr=Hold[(1+2)+3];
ReleaseHold@Map[Hold,expr,{2}]

Out[2]= Hold[3]+Hold[1+2]

Вы можете играть в различные игры в этом направлении, но поскольку я не могу сказать, что именно вы хотите сделать, немного трудно быть конкретным. Что-то, что может быть полезным, это определить свой собственный Hold, который спускается так, как вы хотите:

SetAttributes[DescentHold,{HoldAll}]
DescentHold[a_Plus]:=ReleaseHold@Map[DescentHold,Hold[a],{2}]
DescentHold[a_]:=Hold[a]

Обратите внимание, что этот приближается к внешним Holdам после того, как внутренние обернуты, так что, например, плоскость Plus начинает действовать:

DescentHold[2*3+(4+5)]
Out[4]= Hold[4]+Hold[5]+Hold[2*3]
2
ответ дан 5 December 2019 в 17:34
поделиться

Как это часто бывает, когда вы хотите сделать что-нибудь хитрое в системе Mathematica, на помощь приходят сопоставление с образцом и замена правил. Однако в этом случае вам нужно сделать что-то странное , и вы должны использовать Replace вместо ReplaceAll ( /. оператор), чтобы вы могли воспользоваться его необязательным третьим аргументом, чтобы задать ему уровень. Используя предложенный вами пример:

In[1]:= Replace[
         Hold[Plus[Plus[2, 2], 2]],
         expr_Plus :> With[{eval = expr}, eval /; True],
         {2}]
Out[1]= Hold[4 + 2]

Бесполезное на вид

expr_Plus :> With[{eval = expr}, eval /; True]

правило на самом деле документированный способ совместного использования локальных переменных между тестовым соответствием и телом структуры With ; здесь вы ничего не делаете с локальной переменной, а заставляете ее вычислять окольными путями --- потому что менее окольные пути не работают!

ИЗМЕНИТЬ, чтобы добавить: Я думаю, вы неправильно интерпретируете результат Уровень ; два выражения на уровне {2} этого выражения: 2 и Plus [2, 2] ; вы можете увидеть это, используя необязательный третий аргумент для уровня, который делает что-то похожее на необязательный третий аргумент Extract :

In[2]:= Level[Hold[Plus[Plus[2, 2], 2]], {2}, Hold]
Out[2]= Hold[2 + 2, 2]

Со спецификацией уровня {2} , Replace попытается сопоставить и заменить правило для этих двух выражений и будет работать со вторым.

3
ответ дан 5 December 2019 в 17:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: