# Does Set vs. SetDelayed have any effect after the definition was done?

I was always assuming that the only difference between Set (=) and SetDelayed (:=) is that SetDelayed holds the right argument, so that a := b is effectively the same as a = Unevaluated[b]. Especially I assumed that after the assignment is done, there's no further difference for variables or functions assigned with Set and variables assigned with SetDelayed. Looking at OwnValues resp. DownValues seems to support that assumption.

However I now noticed that when writing ?a, Mathematica displays the type of assignment used for the definition, which means it has to store it somewhere. And I somehow doubt that it only stores it in order to show it with ?.

Therefore my question is: Is there any difference in the behaviour of values assigned with = and with := (apart from the different output of ?), assuming the actual assigned expression is the same (i,e, OwnValues/DownValues have the same value after both assignments)?

-
–  Mr.Wizard Jun 2 '12 at 22:14

Yes, at least in one place.

x = {1, 2, 3}
x[[2]] = 8;


All right there, but

y := {1, 2, 3}
y[[2]] = 8


gives Set::noval: Symbol y in part assignment does not have an immediate value

Credit to this old comment by Leonid. Also note the point on memory usage:

[...] I'd guess that delayed definitions may use some intermediate internal variables, while immediate ones point straight to the memory where the data is stored.

-
Beat me to it - +1. –  Leonid Shifrin Jun 2 '12 at 18:24
I knew you were coming @LeonidShifrin –  Rojo Jun 2 '12 at 18:25
That's really interesting. Are there any other cases where there's a difference, esp. one involving DownValues? The obvious idea x[1]={1,2,3};y[1]:={1,2,3} doesn't work because x[1][[2]] already cannot be assigned. –  celtschk Jun 2 '12 at 19:00
@celtschk While this is not directly related, you may find this discussion also interesting. In particular, RuleDelayed inside DownValues is not totally inert (contrary to a popular belief, it does evaluate the r.h.s. of the rule, albeit in a special way). Consider ClearAll[f]; f[x_] := Unevaluated@Unevaluated[x];, and contrast DownValues[f] with Block[{RuleDelayed = HoldComplete}, DownValues[f]], for instance. –  Leonid Shifrin Jun 2 '12 at 20:19
@celtschk Not so simple: InternalInheritedBlock[{RuleDelayed}, SetAttributes[RuleDelayed, HoldAllComplete]; Hold[f[1]] /. DownValues[f]]. As I said, the whole point is not that DownValues are not used (which is in some sense true but not really the cause here), but that RuleDelayed in DownValues evaluates it's r.h.s. and strips any number of Unevaluated` wrappers. In the above code, I prevented that, thus the result. –  Leonid Shifrin Jun 2 '12 at 20:48