# How do I use the third and fourth arguments of Parenthesize?

Parenthesize seems to do a good job with constructing boxes that need to be appropriately parenthesized:

RowBox[Parenthesize[#, TraditionalForm, Null, Null] & /@ {a, a + b, c}] I didn't know what to put in the final two arguments of Parenthesize so I just put Null. It seems to work without problems.

But it would be nice to know what they do. Does anybody know?

I learned about its existence by seeing how the boxes for InverseFunction is made:

InverseFunction (*To load box definitions*)

<< GeneralUtilities
PrintDefinitions[InverseFunction]


Then scroll down to the penultimate definition, and you'll see (inside the Module):

SuperscriptBox[Parenthesize[BoxFormf, BoxFormfmt, Power, Left],
RowBox[{"(", RowBox[{"-", "1"}], ")"}]]


An good explanation can be found an old mathgroup archive thread which I have reconstructed:

When you create a typeset form for a function or operator, you must write a MakeBoxes definition for that function. For example, if you want Transpose[A] to have the typeset form $A^T$ then you might, erroneously, write it this way:

  Transpose /: MakeBoxes[Transpose[matrix_], TraditionalForm] :=


This is erroneous because Transpose[A + B] would typeset as $A + B^T$ which looks like A + Transpose[B], since superscripting by convention has higher precedence than addition. You want it to typeset as $(A+B)^T$

To achieve this, the typesetting of 'matrix' in your definition must be informed of the context in which 'matrix' occurs, so that it can decide if the outermost operator in 'matrix' has a low enough precedence that it must be parenthesized.

Parenthesize[] fits this bill, taking the same first two arguments as MakeBoxes, and taking additional arguments to specify what the enclosing operator is, and perhaps also on which side of it the expression-to-be-typeset falls.

So the correct rule for Transpose is:

  Transpose /: MakeBoxes[ Transpose[list_], TraditionalForm] :=
SuperscriptBox[
"T"
]


This function probably ought to be mentioned somewhere, since it is important, even if it is replaced with something better later.

• Strictly speaking these rules should be defined directly on MakeBoxes rather than as upvalues on Transpose, both since the system is designed to work that way, and because Transpose is protected. – Oleksandr R. May 4 '16 at 21:07
• @OleksandrR , actually according to @ItaiSeggev, TagSetDelayed is preferable for MakeBoxes. Do you believe he is in error? – QuantumDot Jul 29 '17 at 18:36
• @QuantumDot it is a different situation. For a user-defined function, obviously the definitions should be made on that, rather than on MakeBoxes. But MakeBoxes itself is deliberately not Protected, so that one can make definitions on it if desired (for example, if there's no better way to make them). Transpose is Protected, and moreover it is sufficiently fundamental a function that I can imagine it might lose "foreign" definitions without warning, like Times and Plus do. – Oleksandr R. Aug 24 '17 at 20:56

You can check also the docs for PrecedenceForm for examples. Precedence can be used to force parenthesization. If you put a low-ish number, you will likely get a parenthesis. I am afraid I cannot help with the fourth argument (group).

• Do you mean to check docs for PrecedenceForm? I think you're right about the third argument. – QuantumDot Apr 22 '16 at 17:17
• The third argument seems to work properly not with an Integer but with Plus, Times or Power. I can't seem to find other Heads one can use in the third argument. – QuantumDot Apr 22 '16 at 17:25
• @QuantumDot yes of course, edited. thanks – magma Apr 22 '16 at 17:35

Here are a couple more comments about the use of the 3rd and 4th arguments of Parenthesize.

Grouping

First, the 4th argument is useful when the expression to be parenthesized is a binary infix operator that is left or right associative. For example, Rule is a binary operator that is right associative. It is a binary operator:

SyntaxInformation[Rule]


{"ArgumentsPattern" -> {_, _}}

It is right associative because that's how it parses:

a -> b -> c //FullForm


Rule[a,Rule[b,c]]

This means that when Rule is on the RHS of a rule it does not need parentheses, but when it is on the LHS it does need parentheses. This is exactly what Parenthesize returns:

Parenthesize[a -> b, StandardForm, Rule, Right]
Parenthesize[a -> b, StandardForm, Rule, Left]


RowBox[{"a", "\[Rule]", "b"}]

RowBox[{"(", RowBox[{"a", "\[Rule]", "b"}], ")"}]

An example of a left associative operator is CircleMinus:

SyntaxInformation[CircleMinus]


{"ArgumentsPattern" -> {_, _}}

It is left associative:

a ⊖ b ⊖ c //FullForm


CircleMinus[CircleMinus[a,b],c]

When on the LHS no parentheses are needed, but they are needed on the RHS:

Parenthesize[a ⊖ b, StandardForm, CircleMinus, Left]
Parenthesize[a ⊖ b, StandardForm, CircleMinus, Right]


RowBox[{"a", "⊖", "b"}]

RowBox[{"(", RowBox[{"a", "⊖", "b"}], ")"}]

Numerical precedence

Sometimes it's convenient to specify the precedence numerically instead of through a symbol. This can be done by using a list consisting of the precedence and grouping of the container. For example, Times has precedence:

Precedence[Times]


400.

If you want to parenthesize an expression only when the precedence is less than Times, you can use the list form in Parenthesize:

Parenthesize[a b, StandardForm, {399, None}]
Parenthesize[a b, StandardForm, {400, None}]


RowBox[{"a", " ", "b"}]

RowBox[{"(", RowBox[{"a", " ", "b"}], ")"}]

You might wonder about using different grouping specifications (other than None`), but as far as I can tell the grouping specification never influences parenthesization. I could easily be wrong about this, though.