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表达式).这可能吗?
我不知道这样的"开箱即用",但是可以通过隐藏不需要替换的表达式,一些临时符号,然后应用规则,然后恢复这些表达式来实现类似的效果.这是一种方式:
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)
我定义ReplaceProtect与UpValues在一个相当普遍的方式,因此它也可以使用Replace等功能,其使用的规则.
由于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]
另一种方法是使用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
Run Code Online (Sandbox Code Playgroud)
x - y + v[a, b]