Jon Harrop wrote:
> Yaroslav Bulatov wrote:
>
>>The following gives an error
>>f = 5; f[a_] = a
>>
>>Set is HoldFirst, so why does it evaluate it's first argument f[a_]?
>
>
> Conversely, why do the attributes of Set and SetDelayed indicate that they
> hold their first argument when the kernel evaluates it.
>
As David Bailey wrote, Set and SetDelayed do have HoldFirst attributes
so that they can see the left hand side before evaluation. That doesn't
mean that they are not able to evaluate all or part of the left hand
side in doing their function. In this case, Set and SetDelayed need to
know the head of the expression to attach a DownValue to the
appropriate head. Here is an example where you can see how things are
working. First create two HoldFirst functions, and set one equal to the
other:
SetAttributes[{f,g},HoldFirst]
f=g
Now, give f a down value:
f[1+2]:=foo
Check Information for f:
In[5]:=
??f
Global`f
Attributes[f] = {HoldFirst}
f = g
Notice that there is no DownValue associated with f[1+2]=f. This is
because SetDelayed first evaluated the head of f[1+2] and discovered
that it was really g. Now check the Information for g:
In[6]:=
??g
Global`g
Attributes[g] = {HoldFirst}
g[1 + 2] := foo
Notice that g has gotten a DownValue, and the argument of g is 1+2 and
not 3. To summarize, SetDelayed evaluated the head but not the argument
when given a first argument of f[1+2].
> On a related note, how can you define and use a downvalue that matches
> g[1+2] without evaluating the 1+2?
>
One possibility:
SetAttributes[g,HoldFirst]
g[Plus[a__]]=Hold[a]
In[10]:=
g[1+2]
Out[10]=
Hold[1,2]
Carl Woll
Wolfram Research