# Cannot Block Plus

It is customary to use the following idiom to partially evaluate something inside a held expression:

f[x_] := 2 x
Block[{f}, Hold[f[1 + 1]] /. x_f :> With[{r = x}, r /; True]]

Out[]= Hold[f]


This works also with built-in symbols, like

Block[{Abs}, Hold[Abs[1 + 1]] /. x_Abs :> With[{r = x}, r /; True]]

Out[]= Hold[Abs]


However, I cannot understand the behaviour of the following

Block[{Plus}, Hold[1 + 2*2] /. x_Plus :> With[{r = x}, r /; True]]


which returns Hold instead of Hold[1+4]. Can someone explain why?

• Times has the same issue, so I suspect they're wired into the parser at a deep lvl in the name of efficiency. Aug 3 '15 at 18:24
• Aug 3 '15 at 18:51
• I believe this is the reason: mathematica.stackexchange.com/questions/19126/… Aug 4 '15 at 0:59

I think my answer to Why does this pattern with Plus not work for numbers? is also the answer here.

See Plus in the reference manual:

Unlike other functions, Plus applies built-in rules before user-defined ones. As a result, it is not possible to make definitions such as 2+2=5.

The ability for user-defined rules to supersede built-in ones was lost in Version 3.

There is a similar property for Times.

Here is some evidence that rules for Plus are applied internally even when Plus is blocked:

Block[{Plus}, 1 + 2*2 /. Plus -> List]
(*  5  *)

p[x__] := Plus[x];
Block[{p}, p[1, 2*2] /. p -> List]
(*  {1, 4}  *)


Update -- some more evidence:

Block[{Plus},
Hold[1 + 2*2] /. x_Plus :> With[{r = x}, r /; True]] // Trace Block[{p},
Hold[p[1, 2*2]] /. x_p :> With[{r = x}, r /; True]] // Trace • Michael, I marked this question as a duplicate. Please let me know if you disagree. Also I suspect you meant to link to 19126 rather than 3261 when you wrote "my answer to ..." Aug 4 '15 at 1:40
• @Mr.Wizard I don't disagree. I considered proposing it, but I wasn't sure I had nailed the reason. -- And thanks, for pointing out I had copied the wrong link! Aug 4 '15 at 1:43
• It occurs to me that I have a work-around that is applicable here but not in the original as marked. Do you think I should reopen for that or just append it here in passing? Aug 4 '15 at 1:49
• @Mr.Wizard If it were me with such a work-around, I would probably nominate for re-opening. (I have done so in the past.) But it's up to you. Aug 4 '15 at 1:54
• I posted. Let me know what you think or if you find problems with it, please. Aug 4 '15 at 5:46

I closed this as a duplicate of Why does this pattern with Plus not work for numbers? but I think I have something that is general enough to be useful, and it's not applicable to that question.

We may observe that although a plain use of Block[{Plus}, . . .] does not prevent numeric evaluation of Plus we can still make a substitution that does:

Block[{Plus = plus}, Hold @@ {2 + 2}]

Hold[plus[2, 2]]


From there we could replace plus with Plus again. Automating this process:

Attributes[hardBlock] = {HoldAll};

hardBlock[sym : {___Symbol}, body_] :=
Block[sym, sym = #; body] /. Thread[# :> sym] & @ Module[sym, sym]


Now:

expr := Hold @@ {1 + 2 + 3*4}

Block[{Plus, Times}, expr]   (* original Block behavior for reference *)

hardBlock[{Plus},        expr]
hardBlock[{Times},       expr]
hardBlock[{Plus, Times}, expr]

Hold

Hold[1 + 2 + 12]
Hold[3 + 3 4]
Hold[1 + 2 + 3 4]


And for completeness:

hardBlock[{Plus}, Hold[1 + 2*2] /. x_Plus :> With[{r = x}, r /; True]]

Hold[1 + 2 2]

• Have you looked at hardBlock[{Plus}, Hold[1 + 2*2] /. x_Plus :> With[{r = x}, r /; True]] // Trace? I think the Plus inside Hold is neither changed nor replaced. Consider hardBlock[{Plus}, Hold[1 + 2*2] /. HoldPattern[x_Plus] :> With[{r = x}, r /; True]] instead. (The thing that made me wonder was that 2*2 did not become 4.) Aug 4 '15 at 11:13
• @Michael Thank you! I worried there would be problems like that I had failed to think through. I'll have to consider how this case might be improved, or if this construct still has a purpose. :-/ Aug 4 '15 at 18:26