禁止ReplaceAll替换(/.)

pha*_*234 5 wolfram-mathematica

从Mathematica自己的文档:

{g[1],Hold[g[1]]}/.g[n_]:>n+1
Run Code Online (Sandbox Code Playgroud)

导致

{2, Hold[1 + 1]}
Run Code Online (Sandbox Code Playgroud)

我的问题:有没有办法保护子表达式不被ReplaceAll取代?我使用复合构造作为变量,如

v[a, b]
Run Code Online (Sandbox Code Playgroud)

并希望能够做这样的事情

v[a, b] + a - b /. {a -> x, b -> y}
Run Code Online (Sandbox Code Playgroud)

导致

v[a, b] + x - y
Run Code Online (Sandbox Code Playgroud)

并不是

v[x, y] + x - y
Run Code Online (Sandbox Code Playgroud)

没有复杂的模式.不幸的是,使用替换和级别规范不是选项.

这个成语

v[a, b] + a - b /. {catch_v -> catch, a -> x, b -> y}
Run Code Online (Sandbox Code Playgroud)

因为'catch_v - > catch'禁止后续规则应用于v.但是我宁愿禁止在表达层面上替换(使用某种Hold或HoldForm表达式).这可能吗?

Leo*_*rin 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}
         ]  
   ]
Run Code Online (Sandbox Code Playgroud)

以下是如何使用它:

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]
Run Code Online (Sandbox Code Playgroud)

我定义ReplaceProtectUpValues在一个相当普遍的方式,因此它也可以使用Replace等功能,其使用的规则.


Mr.*_*ard 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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
x - y + v[a, b]