Incompatibility of Row and TeXForm

Bug introduced in 9.0 and persisting through 11.0

Update: Since no one has been able to give a reason for this change in behavior or provide a solution I am tagging this as a bug. Please report it to Wolfram Support if this affects your use of Mathematica.

In Mathematica 7 Row and TeXForm work harmoniously:

{x^a, Sqrt@b, ArcSin[c]} // Row // TeXForm

x^a\sqrt{b}\sin ^{-1}(c)


As LaTeX:

$$x^a\sqrt{b}\sin ^{-1}(c)$$

TeXForm::unspt: TeXForm of TemplateSlotSequence[1,] is not supported. >>

This error was reported in version 9 as well.

An attempt at a workaround is to substitute Grid for Row but the LaTeX code generated is different:

{{x^a, Sqrt@b, ArcSin[c]}} // Grid // TeXForm


And it formats differently:

$$\begin{array}{ccc} x^a & \sqrt{b} & \sin ^{-1}(c) \\ \end{array}$$

The documentation for TeXForm indicates that it is extensible with rules for Format but I could not find a rule that worked. While I can manually convert a single Row as follows:

StringJoin[ToString /@ TeXForm /@ {x^a, Sqrt@b, ArcSin[c]}]

x^a\sqrt{b}\sin ^{-1}(c)


(Though note that one must copy as Plain Text.)

However attempting to make this a Format rule results in double-conversion and I get this:

What is the best work-around for the problem, preferably automatic?

• does this help (TeXForm /@ {x^a, Sqrt@b, ArcSin[c]}) // Row – Algohi Jul 20 '14 at 7:58
• @Algohi Thanks, but not really. This is similar to my own attempt near the bottom and it still doesn't allow for automatic conversion where Row is part of a larger expression. – Mr.Wizard Jul 20 '14 at 8:20
• So have you reported it again Mr.W? – Jacob Akkerboom Jul 20 '14 at 9:33
• @Jacob No I have not. I was waiting to see what others had to say about this. – Mr.Wizard Jul 20 '14 at 9:42
• @Mr. Wizard I usually use RowBox and DisplayForm to get LaTex code from MM. I don't know if it works in MM10, since I don't have one. TeXForm /@ {x^a, Sqrt@b, ArcSin[c]} // RowBox // DisplayForm – Putterboy Jul 21 '14 at 19:07

SystemConvertCommonDumptemplateBoxToDisplay = BoxFormTemplateBoxToDisplayBoxes


Background

The basic approach used by TeXForm is to create TraditionalForm boxes, and then to convert those boxes into a TeXForm string. The basic internal function that TeXForm uses to convert boxes into a string is SystemConvertTeXFormDumpmaketex. For example, consider BesselJ[n, x]. The TraditionalForm boxes are:

MakeBoxes[BesselJ[n, x], TraditionalForm]


TemplateBox[{"n", "x"}, "BesselJ"]

Notice how SystemConvertTeXFormDumpmaketex is used to convert the above boxes into a string:

TracePrint[
ToString[BesselJ[n, x], TeXForm],
_SystemConvertTeXFormDumpmaketex,
TraceInternal->True
]


SystemConvertTeXFormDumpmaketex[TemplateBox[{n,x},BesselJ]]

SystemConvertTeXFormDumpmaketex[RowBox[{SubscriptBox[J,n],(,x,)}]]

...

"J_n(x)"

By default, SystemConvertTeXFormDumpmaketex uses SystemConvertCommonDumpExpandTemplateBoxes to convert TemplateBox objects into normal boxes:

TracePrint[
SystemConvertTeXFormDumpmaketex[TemplateBox[{"n","x"},"BesselJ"]],
_SystemConvertCommonDumpExpandTemplateBoxes
]


SystemConvertCommonDumpExpandTemplateBoxes[TemplateBox[{n,x},BesselJ]]

SystemConvertCommonDumpExpandTemplateBoxes[TemplateBox[{n,x},BesselJ],Display]

"J_n(x)"

and:

SystemConvertCommonDumpExpandTemplateBoxes[TemplateBox[{"n","x"},"BesselJ"]]


RowBox[{SubscriptBox["J", "n"], "(", "x", ")"}]

Summarizing, TeXForm does the following:

1. Create TraditionalForm boxes
2. Convert TemplateBox objects into normal boxes
3. Convert normal boxes into a TeXForm string

The problem with Row

So, where do things go wrong with Row objects? In Mathematica version 7 and earlier, Row objects were formatted as RowBox objects directly, and so there was no need to convert TemplateBox objects into normal boxes. However, starting in versions 8 or 9, Row objects were formatted as TemplateBox objects. For example, in M9 (I don't have ready access to earlier versions):

MakeBoxes[Row[{x, y}], TraditionalForm]


TemplateBox[{"x", "y"}, "RowDefault"]

One possible fix for this issue is to restore the old functionality of formatting Row objects as normal boxes, and this is what the global variable BoxForm$UseTemplateSlotSequenceForRow controls. I don't like this solution, as it means that Row objects will never use TemplateBox, which I think is a shame (I think TemplateBox offers both speed and memory advantages). Also, it only fixes one symptom of the issue, and not the underlying problem. So, let's figure out the underlying problem. TemplateSlotSequence Here is the TemplateBox format for a Row object: boxes = MakeBoxes[Row[{x, y}, None], TraditionalForm]  TemplateBox[{"x", "y"}, "RowNoSeparators"] (I used a Row object with a separator for reasons I will explain later). These are the normal boxes that TeXForm creates for this TemplateBox: SystemConvertCommonDumpExpandTemplateBoxes[ TemplateBox[{"x","y"}, "RowNoSeparators"] ]  RowBox[{TemplateSlotSequence[1]}] Notice the appearance of a TemplateSlotSequence object. This kind of object is not supported by SystemConvertTeXFormDumpmaketex. Also, just like other Slot objects, the TemplateSlotSequence object only has meaning when it is inside of a Function object, so the above output is not a valid form of normal boxes. This is the reason for the error that gets reported: ToString[Row[{x, y}, None], TeXForm]  TeXForm::unspt: TeXForm of TemplateSlotSequence[1] is not supported. "" Single argument Row The above error doesn't happen for single argument Row because SystemConvertTeXFormDumpmaketex was hacked to support it. Compare: TracePrint[ SystemConvertTeXFormDumpmaketex[TemplateBox[{"x", "y"}, "RowNoSeparators"]], _SystemConvertCommonDumpExpandTemplateBoxes ]  SystemConvertCommonDumpExpandTemplateBoxes[TemplateBox[{x,y},RowNoSeparators]] SystemConvertCommonDumpExpandTemplateBoxes[TemplateBox[{x,y},RowNoSeparators],Display] TeXForm::unspt: TeXForm of TemplateSlotSequence[1] is not supported. "" with: TracePrint[ SystemConvertTeXFormDumpmaketex[TemplateBox[{"x", "y"}, "RowDefault"]], _SystemConvertCommonDumpExpandTemplateBoxes ]  "xy" Notice that the "RowDefault" TemplateBox never gets processed by SystemConvertCommonDumpExpandTemplateBoxes because SystemConvertTeXFormDumpmaketex has a special DownValues for this case. Non-Row TemplateSlotSequence issues The failure to support TemplateSlotSequence is not restricted to Row objects. For example: ToString[BellY[a, b, {c, d}], TeXForm]  TeXForm::unspt: TeXForm of TemplateSlotSequence[3,,] is not supported. "Y_{a,b}()" ToString[WignerD[{j, m1, m2}, \[Theta]], TeXForm]  TeXForm::unspt: TeXForm of TemplateSlotSequence[4,,] is not supported. "D_{\text{m1},\text{m2}}^j()" So, changing the formatting of Row so that it doesn't use a TemplateBox is not really sufficient, it won't fix the above errors. Fix The function used by TeXForm to convert TemplateBox objects into normal boxes is SystemConvertCommonDumptemplateBoxToDisplay: TracePrint[ SystemConvertCommonDumpExpandTemplateBoxes[TemplateBox[{"x", "y"}, "RowNoSeparators"]], _SystemConvertCommonDumptemplateBoxToDisplay, TraceInternal->True ]  SystemConvertCommonDumptemplateBoxToDisplay[TemplateBox[{x,y},RowNoSeparators]] RowBox[{TemplateSlotSequence[1]}] Instead of using SystemConvertCommonDumptemplateBoxToDisplay one could use BoxFormTemplateBoxToDisplayBoxes: template = TemplateBox[{"x","y"},"RowNoSeparators"]; SystemConvertCommonDumptemplateBoxToDisplay[template] BoxFormTemplateBoxToDisplayBoxes[template]  RowBox[{TemplateSlotSequence[1]}] RowBox[{"x", "y"}] Note that the latter function produces acceptable boxes. I don't know why TeXForm uses its own custom function to convert TemplateBox objects. So, a simple fix is to redefine SystemConvertCommonDumptemplateBoxToDisplay: SystemConvertCommonDumptemplateBoxToDisplay = BoxFormTemplateBoxToDisplayBoxes;  Now, TeXForm will work properly with any object whose format uses a TemplateSlotSequence TemplateBox: ToString[BellY[a, b, {c, d}], TeXForm] //OutputForm ToString[WignerD[{j, m1, m2}, θ], TeXForm] //OutputForm ToString[Row[{a, b}, ","], TeXForm] //OutputForm  $$Y_{a,b}(c,d)$$ $$D_{\operatorname{m1},\operatorname{m2}}^j(0,\theta ,0)$$ $$a,b$$ • Thank you for such a deep analysis. I am going to bookmark this for later re-reading. One thing for now; you wrote: I think TemplateBox offers both speed and memory advantages – why would this be? – Mr.Wizard Sep 23 '18 at 11:54 The following works in Version 9.0.1.0 and Version 10.0.1.0 BoxForm$UseTemplateSlotSequenceForRow = False;
{x^a, Sqrt@b,  ArcSin[c]} // Row // TeXForm
(* x^a\sqrt{b}\sin^{-1}(c) *)

• What on Earth is that?! +1 :-) – Mr.Wizard Sep 20 '14 at 16:45
• @Mr.Wizard, it is something that show up when I used my whatOnEarthIs function: whatOnEarthIs = ToExpression["??**" ~~ ToString@# ~~ "*"] &; whatOnEarthIs@TemplateSlotSequence:) – kglr Sep 20 '14 at 17:49
• This seems to restore the old behavior therefore I am Accepting it. Nevertheless I believe a bug remains in the current implementation as presumably TemplateSlotSequence is supposed to work and does not. – Mr.Wizard Sep 21 '14 at 11:08
TeXForm /@ {x^a, Sqrt@b, ArcSin[c]} // RowBox // DisplayForm


$x^a\sqrt{b}\sin ^{-1}(c)$

• This works for a single row, as does my own StringJoin method, but I still don't know how to use this for a larger expression that contains a Row. If I use this method (or mine) to convert (only) the Row subexpressions, then apply TeXForm to the entire expression, the output is wrong. I could try to do everything in pieces then assemble them but there are too many possibilities to make that robust. – Mr.Wizard Jul 24 '14 at 10:03

What do you think about the following substitutions?

expr = Row@{x^a, Sqrt@b, ArcSin[c]};

expr /. Row@{x__} :> HoldForm@Times@x // TeXForm


$x^a \sqrt{b} \sin ^{-1}(c)$

expr2 = Row[{x^a, Sqrt@b, ArcSin[c]}, d];

expr2 /. Row[x_, y_] :> HoldForm@*Times @@ Riffle[x, y] // TeXForm


$x^a d \sqrt{b} d \sin ^{-1}(c)$

• I haven't voted for this yet because I am unsure of Times being consistently formatted as a row. Could you comment on that? – Mr.Wizard Sep 20 '14 at 19:27
• @Mr.Wizard As I understand now, not always :( For example, it add parenthesis for Row@{x+y,z}`. Nothing can compete with incredible @kguler's solution. – ybeltukov Sep 20 '14 at 19:51