Here's a way that keeps the right-hand side from evaluating if using RuleDelayed
instead of Rule
.
a = 333;
RuleDelayed[TR[2], TR[5] + TR[h, g]] /.
h_[lhs_, rhs_] :>
h @@ { (* <-- call it Domen's trick *)
Hold[lhs] /. TR[x__] :> TR[a___, x, b___],
Hold[rhs] /. TR[x__] :> TR[a, x, b]} /.
h_[Hold[x_], Hold[y_]] :> h[x, y]
(* TR[a___, 2, b___] :> TR[a, 5, b] + TR[a, h, g, b] *)
The order is: Restructure the code, then evaluate; only if the code is inside Hold[]
, it won't evaluate. Hence the a
and b
in TR[a, x, b]
in the replacement for Hold[rhs]
are not evaluated. And at the end, when Hold[]
is removed, they're either in Pattern[]
or the second argument of RuleDelayed
, which has the attribute HoldRest
; in both cases, they are not evaluated.
If you use Rule
, then you want the right-hand side to evaluate (or at least, you don't care if it does):
a = 333;
Rule[TR[2], TR[5] + TR[h, g]] /.
h_[lhs_, rhs_] :> h @@ {
Hold[lhs] /. TR[x__] :> TR[a___, x, b___],
Hold[rhs] /. TR[x__] :> TR[a, x, b]} /.
h_[Hold[x_], Hold[y_]] :> h[x, y]
(* TR[a___, 2, b___] -> TR[333, 5, b] + TR[333, h, g, b] <-- oops *)
I guess I must have wanted the a
to evaluate on the right but not on the left (Pattern[]
is HoldFirst
and won't evaluate the pattern symbol). I don't know why I wanted to do that. It doesn't make sense. But there it is.
Now imagine you have something less innocuous than Plus[]
on the right-hand side, and you don't want it to evaluate until the code is completely ready. Loose control of evaluation is a source of bugs. It's tricky getting some bits to evaluate and other bits not to. (I hope I've gotten it right here. Where's Leonid?)