9
$\begingroup$

When I use RowBox for MakeBoxes the order of the elements is changed for TraditionalForm, if there is a plus (+) in the list of elements.

MakeBoxes[x, form_] = RowBox[{"b", "+", "a"}];
MakeBoxes[x, StandardForm]
MakeBoxes[x, TraditionalForm]
(* Out[2] = RowBox[{"b", "+", "a"}]
   Out[3] = RowBox[{"a", "+", "b"}] *)

Sometimes Mathematica really makes me wonder. Does this only happen when there is a plus in RowBox? Is there any way to fix this?

$\endgroup$
9
  • 3
    $\begingroup$ FWIW, Block[{TraditionalFormDump`$UseNewTraditionalForm = False},MakeBoxes[x, TraditionalForm]] returns RowBox[{"b", "+", "a"}]. $\endgroup$ Commented Oct 7, 2013 at 17:01
  • 2
    $\begingroup$ FWIW^2, associating the definition to x, which I think it's a good idea, returns what you expect $\endgroup$
    – Rojo
    Commented Oct 7, 2013 at 17:04
  • $\begingroup$ @Leonid, you are using variables The Google does not know about, therefor they do not exist. :-) But you are right. Where can you read about $UseNewTraditionalForm? $\endgroup$
    – Friedrich
    Commented Oct 7, 2013 at 17:27
  • 1
    $\begingroup$ @Mr.Wizard I haven't tested, but probably attaching it to TraditionalForm, or even to MakeBoxes but explicitly as DownValues, may work $\endgroup$
    – Rojo
    Commented Oct 7, 2013 at 22:04
  • 1
    $\begingroup$ @Rojo thanks for correcting me $\endgroup$
    – Mr.Wizard
    Commented Oct 8, 2013 at 1:51

3 Answers 3

7
$\begingroup$

When I see this right, then the evil function is TraditionalFormDump`ordplus. This seems to change the order. The arguments can be extracted from a Trace

TraditionalForm[a + b]; (* Dummy call *)
TraditionalFormDump`ordplus[{{"+", "b"}, {"+", "a"}}, {}]

(* {2,1} *)

If we change this to give a sorted list, then your arguments are not reordered

ClearAll[TraditionalFormDump`ordplus]
TraditionalFormDump`ordplus[l1_, _] := Range[Length[l1]]

MakeBoxes[x, form_] = RowBox[{"b", "+", "a"}];
MakeBoxes[x, StandardForm]
MakeBoxes[x, TraditionalForm]

(* 
  RowBox[{"b", "+", "a"}]
  RowBox[{"b", "+", "a"}]
*)
$\endgroup$
3
  • $\begingroup$ Impressive! How did you find out about TraditionalFormDump`ordplus? A trace does not give me this function. Do you have any idea why this does not happen when I associate the definition to x as Rojo mentioned? $\endgroup$
    – Friedrich
    Commented Oct 7, 2013 at 18:07
  • 1
    $\begingroup$ @Friedrich I believe it does not happen because definitions associated with x are tried before those associated with TraditionalForm (just like with UpValues), and this special bothersome definition is attached to TraditionalForm's FormatValues. Values associated with MakeBoxes (such as your definitions) are tried last. $\endgroup$
    – Rojo
    Commented Oct 7, 2013 at 20:41
  • 1
    $\begingroup$ @Friedrich You have to use TraceInternal->True as option to Trace. $\endgroup$
    – halirutan
    Commented Oct 7, 2013 at 21:20
2
$\begingroup$

halirutan gave a very nice explanation why this only happens in TraditionalForm and not in StandardForm. For completeness I will add the workaround that Rojo mentioned: Associate the definition to x and not to MakeBoxes using UpSet:

MakeBoxes[x, form_] ^= RowBox[{"b", "+", "a"}];

Association with TraditionalForm also works:

Unprotect[TraditionalForm];
TraditionalForm /: MakeBoxes[x, TraditionalForm] = RowBox[{"b", "+", "a"}];
$\endgroup$
1
$\begingroup$

You can also interfere with the sorting done by TraditionalForm by wrapping your boxes in TagBox, InterpretationBox or TemplateBox:

MakeBoxes[x, form_] = TagBox[RowBox[{"b", "+", "a"}], #&];
MakeBoxes[x, StandardForm]
MakeBoxes[x, TraditionalForm]

TagBox[RowBox[{"b", "+", "a"}], #1 &]

TagBox[RowBox[{"b", "+", "a"}], #1 &]

(I would actually use a TagSet here, but for pedagogical reasons I avoided it.) This avoids the need to modify an internal Mathematica symbol, as in the accepted answer (there may also be good examples where the reordering is beneficial, as in multivariate polynomials). Also, as Mr.Wizard points out, the other answers using TagSet only work when x is at the top-level. For example:

y /: MakeBoxes[y, form_] = RowBox[{"b", "+", "a"}];
MakeBoxes[y, TraditionalForm]
MakeBoxes[{y}, TraditionalForm]

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

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

With the TagBox approach, the non-top level example still works:

MakeBoxes[{x}, TraditionalForm]

RowBox[{"{", TagBox[RowBox[{"b", "+", "a"}], #1 &], "}"}]

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.