MakeBoxes

The code below will ensure any difference of two terms is displayed as a difference when you use any form that outputs 2D expressions (StandardForm, MatrixForm, TableForm, etc.). TraditionalForm displays (b-a) even if you don't make a special definition, it also has many other conventions that come with it.

The kernel automatically calls MakeBoxes when it needs to format an

expression using 2D notation. The rules for MakeBoxes specify that how

expressions with a certain form are should be displayed one way, and other

forms should be displayed different ways. Typically a definition says a

certain box structure should be built using parts of the given expression.

The various parts that are used in the box structure are often smaller

expressions that also need to be made into 2D expressions, so MakeBoxes must

be called on these smaller expressions. This continues recursively until

MakeBoxes formats atoms directly into box structures.

When the kernel calls MakeBoxes it passes the form used in the second

argument. The form can be StandardForm, TraditionalForm, MatrixForm, or any

other form that formats the output as 2D expressions. A rule for MakeBoxes

can have a specific form for the second argument as in MakeBoxes[pattn,

StandardForm] in which case the definition is only used for StandardForm.

You can even define your own for using MakeBoxes[pattn, MyForm], and the

provided formatting rules will be used when you evaluate expr//MyForm. In

the definition below the second argument of MakeBoxes is the pattern (form_).

In this case the formatting rule is used for any form that uses 2D

expressions to format the output.

MakeBoxes has the HoldAllComplete attribute. As a result you can't use

MakeBoxes[Evaluate[expr], form] to force the evaluation of (expr). If (expr)

must complete evaluation that can be accomplished using

( MakeBoxes@@{expr,form} ).

The above rules for MakeBoxes will produce a more readable display of

expressions such as the following:

The rules for MakeBoxes are stored as FormatValues.

It may be tempting to write a slightly simpler implementation, but this

simpler implementation has flaws.

The simpler implementation is:

MakeBoxes[(n_Real|n_Integer|n_Rational)a_.+b_/;

Head[b]=!=Plus&&n<0,form_]:=

RowBox[{MakeBoxes[b,form],MakeBoxes@@{n*a,form}}];

In private email Neil Soiffer of Wolfram Research noted that the version

above has a few problems.

(1) The '-' sign is grouped with the subsequent term as a unary "minus",

instead of binary "difference".

This will effect spacing after the minus (not symmetric with respect to '-'

as is easily seen with 'a-b').

(2) Grouping doesn't work well. If one evaluates (a-b) and triple clicks on

the '-' in the output, automatic grouping doesn't work right.

(3) Perhaps the worst problem is that because '-' is interpreted as a unary

minus, there is implied multiplication between the 'a' and the '-b' and so it

will evaluate incorrectly. Evaluate (a-b) and select the output cell, go to

cell | cell properties | cell evaluatable to make the output cell

evaluatable, and then evaluate the cell. The result looks like '-a b'.

Another example

David park noted that the minus sign gets pulled into the sum in the next

input.

By looking at the box structure of the output cell above you can see what we

need to use in a MakeBoxes definition. The input in the next cell does the

job. The first definition ensures the negative sign is factored out, and the

second definition puts the negative sign in the numerator.

Now the negative sign is always factored out.

Created by Mathematica (May 16, 2004)