禁止ReplaceAll替换(/。)

时间:2011-11-14 20:08:54

标签: wolfram-mathematica

来自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 个答案:

答案 0 :(得分:5)

我不知道这样的“开箱即用”,但是可以通过隐藏不需要替换的表达式,使用一些临时符号,然后应用规则,然后恢复那些来实现类似的效果回归表达。这是一种方式:

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和其他使用规则的函数一起使用。

答案 1 :(得分:5)

由于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]

另一种方法是使用CompressUncompress。这可能会更加强大。

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]