# Can I release a pattern without releasing the whole held expression?

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?

• You seem to really need this. Borderline duplicate, but I hesitate to claim that it is full dupe. Let's see what others think. Oct 16 '16 at 20:15
• @LeonidShifrin I too am on the fence about whether this one is a duplicate. Whoops, just slid onto one side of the fence... :) Oct 16 '16 at 22:15
• @WReach Actually, IMO it's great that you did. Oct 16 '16 at 22:41

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]

• Having specialized and detailed answer here is probably much better than just announcing this as a dupe. +1 as always. 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? Oct 17 '16 at 15:35
• @WReach - Sorry, I forgot the HoldForm around the code for expr2 in my previous comment. 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]]. Oct 17 '16 at 15:54