What is the difference between Set and SetDelayed when evaluating the RHS leaves it unchanged?

This is just my guess about what is going on. First, there is really an internal difference between the two approaches, as is shown in the OP. Another place where this difference manifests itself is with the function Language`ExtendedDefinition:

Clear[f];
f[a_] = 2 + a;

Language`ExtendedDefinition[f]

Language`DefinitionList[f->{OwnValues->{},SubValues->{},UpValues->{},DownValues->{HoldPattern[f[a_]]->2+a},NValues->{},FormatValues->{},DefaultValues->{},Messages->{},Attributes->{}}]

Notice the Rule instead of the RuleDelayed in the DownValues rule. For the SetDelayed version:

Clear[g]
g[a_] := 2 + a

Language`ExtendedDefinition[g]

Language`DefinitionList[g->{OwnValues->{},SubValues->{},UpValues->{},DownValues->{HoldPattern[g[a_]]:>2+a},NValues->{},FormatValues->{},DefaultValues->{},Messages->{},Attributes->{}}]

This time the DownValues rule uses RuleDelayed.

So, I think the real question is why the output of DownValues doesn't use Rule:

Clear[f]
f[a_] = 2 + a;

DownValues[f]

{HoldPattern[f[a_]] :> 2 + a}

I think the answer is that if DownValues did use Rule, then the output would be confusing if a had acquired a value after f was defined. Suppose the output of DownValues was:

dv = {HoldPattern[f[a_]] -> 2 + a}

{HoldPattern[f[a_]] -> 2 + a}

At some point, a is given a value:

a = 3;

And then, later, the user wants to know the DownValues of f:

dv

{HoldPattern[f[a_]] -> 5}

The user would be confused into thinking that the RHS of the rule was 5, when it is really 2+a. So, the function DownValues purposefully replaces Rule with RuleDelayed to avoid this confusion. Note that an alternative was to introduce another hold-type wrapper around the output of DownValues, and this is actually what Language`ExtendedDefinition does.


Also, it should be pointed out, that DownValues are the same, but Definition is still different. I guess this might be the "flag" op asked about.

Information displays Definition by calling it. While one might think Information only "illustrates" whatever is kept internally, then probably Definition really is what the kernel knows. Same output, but maybe a semantic difference one could say.

In[32]:= ClearAll[f, a]
f[a_] = a + 2
Definition[f]
f[a_] := a + 2
Definition[f]

Out[33]= 2 + a

Out[34]= Definition[f]

Out[36]= Definition[f]