6

I would like to release only the rules in an expression that held. Is that possible?

ClearAll[a, b, c, expr];
expr = HoldForm[a = 2 b c /. c -> 5]
(* a=2 b c/. c->5 *)

I can release the whole expression:

ReleaseHold@expr
(* 10 b *)

But I would like to do this:

ReleasePattern@expr
(* a = 10 b *)

Unfortunately there is no ReleasePattern command. Is it possible to do this by other means?

Soldalma
  • 1,289
  • 1
  • 9
  • 17

1 Answers1

5

We can define a helper function that will release any component of a held expression that matches a particular pattern:

releaseHeldMatches[patt_] := ReplaceAll[p:patt :> RuleCondition[p]]

We can then use it to release the ReplaceAll that appears in the expression from the question:

expr // releaseHeldMatches[_ReplaceAll]
(* HoldForm[a = 10 b] *)

The function releasePattern from the question can then be defined thus:

releasePattern = releaseHeldMatches[_ReplaceAll];

expr // releasePattern
(* HoldForm[a = 10 b] *)

Both of these work upon some part of the expression that matches a pattern. Perhaps we would like to release a part found at a particular index instead:

releaseAt[i__][expr_] := ReplacePart[expr, {i} -> expr[[i]]]

expr // releaseAt[1, 2]
(* HoldForm[a = 10 b] *)

Note: one might object to releaseHeldMatches operating upon level zero of the held expression, or lament that extracted subexpressions may be held in their own right. I purposely choose not to worry about either of these contingencies, but should one care:

releaseHeldMatchesPedantic[patt_, expr_] :=
    Replace[expr, p: patt :> RuleCondition[ReleaseHold[p]], {1, Infinity}]
releaseHeldMatchesPedantic[patt_][expr_] :=
    releaseHeldMatchesPedantic[patt, expr]
WReach
  • 68,832
  • 4
  • 164
  • 269
  • Having specialized and detailed answer here is probably much better than just announcing this as a dupe. +1 as always. – Leonid Shifrin Oct 16 '16 at 22:40
  • @WReach - Thanks for the answer. I had trouble making releaseAt work with a different expression: expr2=(f[a+2 b c]==g[a,c])/. c->5; Changing the arguments from [1,2] to several other alternatives did not work. Also, is there a way to make releasePatterns work with selected patterns like c->5, leaving others unevaluated? – Soldalma Oct 17 '16 at 15:35
  • @WReach - Sorry, I forgot the HoldForm around the code for expr2 in my previous comment. – Soldalma Oct 17 '16 at 15:42
  • If we have expr3 = HoldForm[(f[a+2 b c] /. a -> 2) == (g[a,c]/. c -> 5)] and define releaseCOnly = releaseHeldMatches[HoldPattern[_ /. c-> 5]];, then we can write expr3 // releaseCOnly to get HoldForm[(f[a + 2*b*c] /. a -> 2) == g[a, 5]]. – WReach Oct 17 '16 at 15:54