In mentally building a model of how Mathematica works, I naively expected Set
to create a Rule
in a symbol's DownValues
, and SetDelayed
to create a RuleDelayed
in a symbol's DownValues
. Therefore, I was a bit surprised when I tested
ClearAll[g];
Set[g[5], 0];
SetDelayed[g[x_], 1];
DownValues[g] // FullForm
and saw
List[RuleDelayed[HoldPattern[g[5]],0],RuleDelayed[HoldPattern[g[Pattern[x,Blank[]]]],1]]
I naively expected to see
List[Rule[HoldPattern[g[5]],0],RuleDelayed[HoldPattern[g[Pattern[x,Blank[]]]],1]]
or even
List[Rule[g[5],0],RuleDelayed[HoldPattern[g[Pattern[x,Blank[]]]],1]]
The extra HoldPattern
and RuleDelayed
seem semantically harmless -- at least I wasn't able to think of a breaking example before breakfast. Looking into the issue, I find the following remarks in the documentation for HoldPattern
(emphases are mine)
The left-hand sides of rules are usually evaluated, as are parts of the left-hand sides of assignments. You can use HoldPattern to stop any part from being evaluated.
The ambiguity of that statement signals that there is a whole lot more going on, here, meaning Set
and SetDelayed
aren't going to be exactly equivalent to the rules one would naively expect, and there must be special cases and exclusions in the works.
I'd be grateful for hints, experiences, opinions, deeper knowledge, suggested experiments, and especially pointers to clarifying documentation.
HoldPattern
is used for the l.h.s., andRuleDelayed
to keep the r.h.s. also unevaluated until the replacement is made. Also, as @Rojo noted, this is not always enough, and some evaluation of the l.h.s. does happen during assignments (which was obviously an intentional design decision). $\endgroup$