How to get the symbol name of a list element?

Let's say we have a list g with variable d as its element:

Clear[g, d]
g = {1,2,3,d}


Now g[[4]] evaluates to d. But after d is assigned, g[[4]] evaluates to d's value. But it seems like g[[4]] is still pointing to d:

In[48]:= d = 1

Out[48]= 1

In[49]:= g[[4]]

Out[49]= 1

In[50]:= d = 2

Out[50]= 2

In[51]:= g[[4]]

Out[51]= 2


So is there anyway to get the symbol of g[[4]]? SymbolName does not work in this case. SymbolName[g[[4]]] results in an error.

• Take a look at OwnValues[g] and FullDefinition[g]. The closest I can get is Extract[First[OwnValues[g]], {2, 4}, Defer] but I cannot take the SymbolName as it's wrapped in Defer and removing that will evaluate it as 2. Commented Aug 7, 2020 at 12:56
• ^ that said, you can get it using strings StringCases[ToString@Extract[First[OwnValues[g]], {2, 4}, Defer], "Defer[" ~~ x_ ~~ "]" :> x] // First Commented Aug 7, 2020 at 13:05
• Closely related to this question.
– Alan
Commented Aug 7, 2020 at 13:15

ClearAll[g, d]
g = {1, 2, 3, d}
Part[g, 4]  (* what you expect *)
Trace[Part[g, 4]] (* how it is produced *)
d = 4; (* assign value *)
Trace[Part[g, 4]]  (* now you get the evaluated part *)
OwnValues[g] // FullForm  (* examine the assignment result *)
Extract[%, {1, 2, 4}, HoldForm]  (* extract what you want *)

• Hi, your output in full form is HoldForm[d] whereas the output of SymbolName would be "d". Commented Aug 7, 2020 at 18:49
• @ChrisDegnen Well, OP said "get the symbol" not "get the symbol name", although yes OP did mention SymbolName. OP can choose. It might be desirable to be able to ReleaseHold at some point. If not, OP can just apply ToString.
– Alan
Commented Aug 7, 2020 at 19:14

You can obtain the name using Hold

Clear[g, d]
g = {1, 2, 3, d};
d = 2;

o = OwnValues[g];
m = MapAll[Hold, o];
h = FirstCase[m, RuleDelayed[_, Hold[z_]] :> z, _, Infinity];
s = ToString[h[[4]]];
n = StringTake[s, {6, -2}]


"d"