# Confusion about HoldFirst attribute of Set

Set has the attribute HoldFirst.
Expectedly the following does not work, i.e. it does not assign the OwnValue of 3 to x:

In[1]:= {x, y}[[1]] = 3

During evaluation of In[1]:= Set::setps: {x,y} in the part assignment is not a symbol.

Out[1]= 3


However, the following does work:

In[2]:= {f, g}[[1]][x_] = x^2

Out[2]= x^2


with the result

?f
Globalf
f[x_]=x^2


Can anyone explain that?

• – Michael E2 Jun 24 '17 at 0:39

The problem is not related to Set in general but to how Set works with Part on a left hand side.

Following Set::setps message documentation

This message is generated when a part assignment is used for the value of an expression other than a symbol.

Part assignments are implemented only for parts of the value of a symbol.

Shortly

Part[(*something*), (*spec*)] = (*value*)


will only work if (*something*) is a symbol so that Set can do in place modification of a part of that symbol. ( how much 'in place' is that is a different topic and I'm not competent to elaborate)

The second example is not a Part assignment, because the head of the lhs is not Part but whole expression: Part[{f, g}, 1].

HoldFirst does not mean it will not be evaluated ever. It is used by Set to detect e.g. whether it is an event of a Part assignment.

Kuba's answer explains why the first form does not work, but it does not address why the second form does work. That has been discussed in other questions

One can see that the head of the left-hand-side is evaluated in each of these cases:

ClearAll[a, b, c, x]
x = {a, b, c};

(# & @@ x)[1] = 1;
Extract[x, 2][1] = 2;
Last[x][1] = 3;

Definition[a, b, c]

a[1] = 1

b[1] = 2

c[1] = 3


Additionally the arguments are evaluated as seen in:

pats = {i_, j_, k_};

Last[x][First[pats]] = i^2;

c[4]

16


The LHS is not fully evaluated before assignment however; instead a special evaluation sequence is used.

With the definitions above in place if one separately evaluates:

Last[x][Last@pats]

k_^2


And if one manually attempts assignment to this it does not work:

k_^2 = 4;

Set::write: Tag Power in k_^2 is Protected. >>


However assigning to the compound expression:

Last[x][Last@pats] = 5;

c[1000]

5

? c

c[1] = 3

c[k_] = 5
`
• I guess Kuba's answer had a hint in the right direction for the second part but your answer made the second part much clearer, thanks. In the end it's all about how the lhs is evaluated before assignment. To be honest, in such cases I usually just try different things using simple examples, since I don't see how to extract such information from the documentation. – kalix Jun 24 '17 at 5:15