Запретить замену на ReplaceAll (/.) - PullRequest
5 голосов
/ 15 ноября 2011

Из собственной документации Mathematica:

{g[1],Hold[g[1]]}/.g[n_]:>n+1

ведет к

{2, Hold[1 + 1]}

Мой вопрос: есть ли способ защитить подвыражения от замены на ReplaceAll? Я использую составные конструкции в качестве переменных, как

v[a, b]

и хотел бы иметь возможность делать такие вещи

v[a, b] + a - b /. {a -> x, b -> y}

ведет к

v[a, b] + x - y

а не

v[x, y] + x - y

без сложных шаблонов. К сожалению, использовать замену и спецификации уровня не вариант.

эта идиома

v[a, b] + a - b /. {catch_v -> catch, a -> x, b -> y}

работает, так как 'catch_v -> catch' запрещает применять последующие правила к v. Но я бы предпочел запретить замену на уровне выражения (с каким-либо выражением Hold или HoldForm). Это возможно?

Ответы [ 2 ]

5 голосов
/ 15 ноября 2011

Поскольку ReplaceAll предназначен для «преобразования каждой части выражения» и часто используется специально для возможности работать внутри Hold вариаций, вам необходимо использовать инертную форму для выражения.

Один из способов - преобразовать ваше выражение в строку. Вот пример:

SetAttributes[holdAsString, HoldFirst]

holdAsString[expr : Except[_String]] := 
 holdAsString @@ {ToString[Unevaluated@expr, InputForm]}

holdAsString[v[a, b]] + a - b /. {a -> x, b -> y} /. holdAsString -> ToExpression
x - y + v[a, b]

Другой метод заключается в использовании Compress и Uncompress. Это может оказаться более надежным.

SetAttributes[holdCompressed, HoldFirst]

holdCompressed[expr : Except[_String]] := 
 holdCompressed @@ {Compress@Unevaluated@expr}

holdCompressed[v[a, b]] + a - b /. {a -> x, b -> y} /. holdCompressed -> Uncompress
x - y + v[a, b]
5 голосов
/ 15 ноября 2011

Я не знаю ничего подобного "из коробки", но можно добиться аналогичного эффекта, скрывая выражения, в которых не нужны замены, с некоторыми временными символами, затем применяя правила и затем восстанавливая их.выражения назад.Вот один из способов:

ClearAll[ReplaceProtect];
ReplaceProtect /: f_[ReplaceProtect[expr_, ptrn_], args___] :=
   Module[{protectRules, ps, n = 0},
      protectRules = 
         Cases[expr, x : ptrn :> (HoldPattern[x] -> ps[n++]), Infinity];
      f[expr /. protectRules, args] /. 
         Replace[protectRules, 
            Verbatim[Rule][Verbatim[HoldPattern][x_], rhs_] :> (rhs :> x), {1}
         ]  
   ]

Вот как можно использовать это:

In[42]:= ReplaceProtect[{g[1],Hold[g[1]]},_g]/.g[n_]:>n+1
Out[42]= {g[1],Hold[g[1]]}

In[43]:= ReplaceProtect[{g[1],Hold[g[1]]},_Hold]/.g[n_]:>n+1
Out[43]= {2,Hold[g[1]]}

In[44]:= ReplaceProtect[v[a,b]+a-b,_v]/.{a->x,b->y}
Out[44]= x-y+v[a,b]

Я определил ReplaceProtect с UpValues в довольно общем виде, поэтомуиспользуется также с Replace и другими функциями, которые используют правила.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...