How to extract part of a held expression without evaluating it

How can I extract part of a held expression without evaluating it?

Clear[w]
Part[HoldForm[w = 3],1,1]
(* w *)
w = 4
Part[HoldForm[w = 3],1,1]
(* 4 *)


Here I would like to obtain "w" again, not its current value. How can I extract the unevaluated symbol on the lhs of the definition, if the symbol has a value already before the definition is made in the hold form? "Part" seems to always evaluate the extracted part of the held expression. Is there a way to prevent this? Of course the problem is the same when I extract part of the rhs of the definition or when I extract any part of any held expression. I would like to use this inside of a function which takes as the argument any expression. This expression is then held and extractions made from it. So the solution should work without knowing in advance what the symbol on the lhs of the definition is and whether it is bound or not.

Thanks for help!

• Use Extract instead, e.g., Extract[HoldForm[w = 3], {1, 1}, Hold] – Carl Woll Sep 13 '18 at 21:25
• @CarlWoll, thanks, this is indeed what I was looking for. But this returns Hold[w]. How do I extract "w" from Hold[w], e.g. for printing it? – Roland Salz Sep 13 '18 at 21:56
• Perhaps you could use HoldForm instead of Hold? – Carl Woll Sep 13 '18 at 22:00
• Yes. Thanks again! – Roland Salz Sep 13 '18 at 22:18
• w = 4; Hold[ w = 3 ][[ {1}, 1 ]] – Kuba Sep 14 '18 at 5:57

Like so:

Attributes@holdFormComplete={HoldAllComplete}
MakeBoxes[holdFormComplete@a_,f_]:=MakeBoxes[HoldForm@a,f];
w=4;
Extract[Hold[w=3],{1,1},holdFormComplete]
%//FullForm
(*w*)
(*holdFormComplete[w]*)


Note that MakeBoxes is also HoldAllComplete, so it won't allow HoldForm to leak no matter what is inside it.

• Why not HoldForm directly? Original Hold is a weak link anyway. – Kuba Sep 14 '18 at 5:57