[Edit: As noted in the comments, you're probably better off using Hold
,ReleaseHold
etc. to solve your problem, since Inactivate
was never designed for this use case. Having said that, below you'll find one possible attempt to replicate the desired behaviour as closely as possible]
The goal
For this answer, I'll try to address the following requirements for a new function myInactivate
:
myInactivate
should replicate the behaviour of Inactivate
for cases where there are no Hold
attributes at play. This includes:
- Nice typesetting
- Localized inactivation in the sense that parts are inactivated separately
- A way to activate only parts again (see possible extensions below)
- Inactivated symbols should still have the same
Hold
attributes as the original symbol
Examples
You can find the code for myInactivate
,myActivate
, etc. at the end of the answer.
myInactivate
can be used just like Inactivate
:
a = 1;
myInactivate[a = 2]
(* myInactive[Set][a, 2] *)
myActivate[%]
(* 2 *)
It also supports the typesetting of Inactive
expressions:
myInactivate[Sum[f[a = 2, z], {n, 1, 2}]]

You can filter out all inactive heads using myInactiveQ
:
myInactivate[Sum[f[a = 2, z], {n, 1, 2}]] //
Cases[#, _?myInactiveQ, All, Heads -> True] &
(* {myInactive[Sum], myInactive[f], myInactive[Set]} *)
You can also manually create inactive symbols using myInactive
:
myInactive[Set][a, 2]

Possible extensions
To make something like this really something with more control than Hold
and related functions, one would need to implement the two argument forms of Inactivate
and Activate
(i.e. filtering of what gets inactivated). This would then allow for selective inactivation, something that is difficult to achieve with Hold
and friends.
How it works
As noted in the comments, composite heads (e.g. Inactive[Set]
) are out, as they can't have any attributes. So the only thing we can to is to replace the heads with a new, inert symbol. This is exactly what myInactive
does (let sym
be the symbol to inactivate):
- If not already done, it creates a new symbol (e.g.
inactivesym
), with the same attributes as sym
(except Protected
and Locked
, for obvious reasons).
- It adds the new symbol
inactivesym
to inactSymbols
, the replacement list to revert inactivation.
- It adds a typesetting rule to typeset
inactivesym[...]
as Inactive[sym][...]
(wrapped in an InterpretationBox
, to ensure that the output can be copied)
- It adds a typesetting rule to typeset
inactivesym
as myInactive[sym]
- It marks
inactivesym
as myInactiveQ
You'll also notice the special casing of List
and Rule
: Apparently, Inactivate
doesn't touch some inert heads such as List
and Rule
, so I've added them here as well.
Code
inactSymbols = <||>;
Attributes[myInactiveQ] = {HoldFirst};
myInactiveQ[_] := False
Attributes[myInactive] = {HoldFirst};
myInactive[h_] := myInactive[h] = With[
{s = Unique["inact" <> SymbolName@Unevaluated@h]},
Attributes[s] = Complement[Attributes[h], {Protected, Locked}];
MakeBoxes[s[args___], frm_] ^:= With[
{b = MakeBoxes[Inactive[h][args], frm]},
InterpretationBox[b, s[args]]
];
AppendTo[inactSymbols, s -> h];
MakeBoxes[s, frm_] ^:= MakeBoxes[myInactive[h], frm];
myInactiveQ[s] ^= True;
s
]
myInactive[s_?myInactiveQ] := s
myInactive[s : List | Rule] := s
Attributes[myInactivate] = {HoldFirst};
myInactivate[expr_] := Replace[
Unevaluated@expr,
{
i : HoldPattern[myInactive[h_][args___]] :> i,
h_Symbol[args___] :> With[
{in = myInactive[h]},
in[args] /; True
]
},
All
]
myActivate[expr_] := expr /. inactSymbols
Function[...]
, but there is no way to prevent expressions of the formFunction[...][...]
from evaluating. You could of course use a different way to inactivate the heads, but making them composite seems like the best way if one wants to preserve the structure of the expression. $\endgroup$ – Lukas Lang Jan 15 '19 at 12:58Set
so it behaves as it wasn't there. If you don't wan't it, what do you expect fromInactivate
? $\endgroup$ – Kuba♦ Jan 15 '19 at 13:01Activate[Inactivate[Inactive[a] = 2]]
? $\endgroup$ – kglr Jan 15 '19 at 13:02Hold
andReleaseHold
? $\endgroup$ – Michael E2 Jan 15 '19 at 13:32Inactive[Set]
that has theHoldFirst
attribute ofSet
. But sinceInactive[Set]
is a composite head, it cannot have attributes, as far as I know. $\endgroup$ – Sjoerd Smit Jan 15 '19 at 16:33