12
$\begingroup$

For learning purposes I created this code:

{g, 3*(10 + g)} /. HoldPattern[Plus[t__]] :> (Plus[t] /. g -> h)

I am learning about HoldPattern. As I understand it HoldPattern makes sure that the pattern is not Evaluated. If this is the case however, then what is the difference with Unevaluated and why does Unevaluated not work in case of patterns?

$\endgroup$
4
  • $\begingroup$ @Kuba, I guess my question is what the difference is between the two in the case of patterns $\endgroup$ Commented Aug 16, 2017 at 13:07
  • 1
    $\begingroup$ Will delete my previous comment as I am not sure I understood the question but I don't have time to focus now. Let me leave the old related link 112842 and another closer one: 110499 $\endgroup$
    – Kuba
    Commented Aug 16, 2017 at 13:13
  • 2
    $\begingroup$ This is the same as asking about the difference between Hold (or anything with a Hold* attribute) and Unevaluated. Google for this and you'll find several discussions (many point to the Villegas tutorial). Unevaluated gets stripped out in the first "evaluation step". Its argument will get evaluated during the second step. $\endgroup$
    – Szabolcs
    Commented Aug 16, 2017 at 13:26
  • 2
    $\begingroup$ Try Unevaluated[1 + 1], Unevaluated[1 + 1] + 1 and Hold[1 + 1] + 1 and TracePrint their evaluations. The first one is a special case because evaluation stops when Unevaluated[...] reach the top level. The second one evaluates to (1+1)+1 which then evaluates further immediately. $\endgroup$
    – Szabolcs
    Commented Aug 16, 2017 at 13:28

1 Answer 1

15
$\begingroup$

HoldPattern is a persistent head that prevents evaluation of its argument(s) yet is transparent to pattern matching. Unevaluated is a temporary wrapper that prevents the evaluation of a single argument* by a single head at one point in the evaluation, and then is stripped. Once it is stripped it cannot have any further effect on the evaluation.

You can use Unevaluated in your example pattern, but it must wrap the entire rule rather than only the left hand side:

{g, 3*(10 + g)} /. Unevaluated[Plus[t__] :> {t}]    (* simplified RHS for clarity *)
{g, {30, 3 g}}

Unevaluated[Plus[t__]] :> {t} would not work even if Unevaluated acted normally(1) because it would only prevent RuleDelayed from evaluating Plus[t__] but the entire rule would be (re)evaluated by ReplaceAll and Plus[t__] reduced to t__.


* Although undocumented and even marked in red as a syntax error Unevaluated will accept multiple arguments, and when activated it effectively transforms into Sequence while simultaneously holding. This transformation takes place after the Sequence would be flattened in the normal evaluation procedure, so it remains as a single expression even if the head (f below) does not have SequenceHold or HoldAllComplete.

ClearAll[f]

f[x_] := HoldComplete[x]

f[Unevaluated[1 + 1, 2 + 2, 3 + 3]]
HoldComplete[Sequence[1 + 1, 2 + 2, 3 + 3]]

Observe that Sequence[1 + 1, 2 + 2, 3 + 3] is bound to the single parameter pattern x_, rather than becoming f[1 + 1, 2 + 2, 3 + 3] which would not match the definition given. In other words the behavior is the same as:

f[Unevaluated @ Sequence[1 + 1, 2 + 2, 3 + 3]]
$\endgroup$
6
  • 2
    $\begingroup$ Excellent answer. No single word that is not needed, and yet a complete description. Your text is as terse yet functional, as your code. My hat is off. $\endgroup$ Commented Aug 16, 2017 at 21:23
  • $\begingroup$ @Leonid I am sincerely flattered. $\endgroup$
    – Mr.Wizard
    Commented Aug 17, 2017 at 4:44
  • $\begingroup$ @Leonid I thought of something to add. Hopefully it is useful and does not detract too much from the pithiness of the answer. $\endgroup$
    – Mr.Wizard
    Commented Aug 17, 2017 at 4:55
  • 1
    $\begingroup$ “… because it would only prevent RuleDelayed from evaluating Plus[t__] but the entire rule would be (re)evaluated by ReplaceAll and Plus[t__] reduced to t__.” Maybe I missed something, but I think it's not true? Unevaluated[Plus[t__]] :> {t} will evaluate to t__ :> {t} even when it's outside of ReplaceAll. $\endgroup$
    – xzczd
    Commented Aug 17, 2017 at 11:41
  • $\begingroup$ @xzczd Right, that's what I meant by "even if Unevaluated acted normally" -- see the superscript link next to that phrase for a related discussion. Perhaps I can think of a better way to write that. $\endgroup$
    – Mr.Wizard
    Commented Aug 18, 2017 at 18:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.