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

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] :=
    SuperscriptBox[MakeBoxes[matrix, TraditionalForm], "T"]

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[
      Parenthesize[list, TraditionalForm, Power, Left],
      "T"
    ]

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


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).


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.