# How can I define MakeBoxes for Inactive forms of user-defined heads?

Here I define a MakeBoxes for Times:

MakeBoxes[p : Inactive[Times][args___], form_] :=


And it works as expected:

Inactivate[Times[3, 5, 2, 3]]


But when I define it for my own head myTimes,

MakeBoxes[p : Inactive[myTimes][args___], form_] :=


it doesn't work:

Inactivate[myTimes[3, 5, 2, 3]]


Two questions:

1. Why doesn't it work for user-defined symbols:
2. What do I need to do to make it work?
• What is FullForm of Inactivate[myTimes[3, 5, 2, 3]]? I don't have version 10 installed but it seems to me that Inactivate must behave differently when operating on different functions. – Oleksandr R. May 21 '16 at 19:14
• Also there is a problematic infinite recursion over p when making boxes for this MakeBoxes rule (as when one writes Information[MakeBoxes]). Recursion is not necessary in this case since you can just use MakeBoxes[p : Inactive[Times][args___], form_] := With[{boxes = MakeBoxes[HoldForm@myHead[args], form]}, InterpretationBox[boxes, p]], i.e. produce the InterpretationBox directly. – Oleksandr R. May 21 '16 at 19:26
• @OleksandrR. the FullForm of Inactivate[myTimes[3, 5, 2, 3]] is Inactive[myTimes][3, 5, 2, 3], so I would have expected MakeBoxes to work. – QuantumDot May 22 '16 at 22:14
• You could "protect" myTimes from being caught by "catch-all" Inactive format-value, by using BoxFormUsesPreInPostFixOperatorQ[myTimes] = True, then your MakeBoxes definition for myTimes would work. But since UsesPreInPostFixOperatorQ has HoldAllComplete attribute, up-value on myTimes changing UsesPreInPostFixOperatorQ doesn't work, and redefining undocumented function seems more evil than changing FormatValues[Inactive]. – jkuczm May 28 '16 at 10:38
• @jkuczm well, maybe since it not a Protected function, it is meant to be modified as needed? It would be nice to know what BoxFormUsesPreInPostFixOperatorQ really does. It yields True for things with special notation like Dot, Plus, NonCommutativeMultiply, and False for most other symbols. – QuantumDot May 28 '16 at 11:27

You need to reorder the way definitions of Inactive are applied once you've defined your custom one. By default it was put at the bottom, so the "catch-all" rule is being attempted first.

Unprotect[Inactive];

Inactive /: MakeBoxes[p : Inactive[myTimes][args___], form_] :=

FormatValues[Inactive] = RotateRight[FormatValues[Inactive]];

Inactive[myTimes][1, 2, 3]

myHead[1, 2, 3]

• That's interesting... I probably wouldn't have figured that out. Couple Qs: Is it important to have the rule associated to Inactive rather than to MakeBoxes directly? Will user-defined rules always go to the bottom (meaning I should use RotateRight after every definition)? – QuantumDot May 26 '16 at 16:36
• @QuantumDot If you don't use the TagSetDelayed, the definition will be associated with MakeBoxes and to me it makes more sense to overload Inactive. This way if you make tons of overloaded MakeBoxes definitions, the definitions are spread out amongst many Heads, rather than one Head having tons of definitions. Makes things more clean IMO. – Chip Hurst May 26 '16 at 18:54
• @QuantumDot and as far as I know, Mathematica tries to order (top level) definitions from least general to most general. It's usually good about doing this, but in general it can mess up (because how does one generically define which definition is more general?). I think this is just one of those cases. (At least from my experience, I think that's what's going on.) – Chip Hurst May 26 '16 at 18:57