4
$\begingroup$

If I define the TraditionalForm formatting of myFunction without TemplateBox, then TeXForm works properly:

ClearAll[myFunction]
myFunction /: HoldPattern[MakeBoxes[myFunction[a_, b_, c_], TraditionalForm]] := 
  SubsuperscriptBox[ToBoxes[a], ToBoxes[b], ToBoxes[c]]


myFunction[h, 1, 2] // TeXForm
(* h_1^2 *)

But if I try to define it using TemplateBox,

ClearAll[myFunction]
myFunction /: HoldPattern[MakeBoxes[myFunction[a_, b_, c_], TraditionalForm]] := 
  TemplateBox[
    {ToBoxes[a], ToBoxes[b], ToBoxes[c]}, "myFunctionTag", 
    DisplayFunction :> (SubsuperscriptBox[#1, #2, #3] &)
  ];

TraditionalForm works correctly,

myFunction[h, 1, 2] // TraditionalForm

(* $h_1^2$ *)

but TeXForm does not return code to format the expression as in TraditionalForm:

myFunction[h, 1, 2] // TeXForm
(* \text{myFunctionTag}[h,1,2] *)

Instead, it is just replacing the head of the function with the tag of TemplateBox. What is the correct way to make TeXForm generate code out of a TemplateBox? I'm looking for a solution that can be programmed into a package.

$\endgroup$
5
  • 2
    $\begingroup$ Try using Rule instead of RuleDelayed in your TemplateBox definition. $\endgroup$
    – Carl Woll
    Commented Jul 30, 2017 at 21:46
  • $\begingroup$ D'oh! Voting to close. $\endgroup$
    – QuantumDot
    Commented Jul 30, 2017 at 22:33
  • 3
    $\begingroup$ The docs indicate that RuleDelayed is acceptable in a TemplateBox, so I don't think it's a bad question $\endgroup$
    – Carl Woll
    Commented Jul 30, 2017 at 22:34
  • $\begingroup$ @CarlWoll Please write an answer to this question, so I can accept. $\endgroup$
    – QuantumDot
    Commented Jul 31, 2017 at 18:28
  • $\begingroup$ Not relevant to the question, but note that using ToBoxes instead of MakeBoxes, on RHS, introduces evaluation leaks. $\endgroup$
    – jkuczm
    Commented Aug 1, 2017 at 10:00

1 Answer 1

6
$\begingroup$

The internal function used by TeXForm to process boxes is System`Convert`CommonDump`ExpandTemplateBoxes. This function is expecting the DisplayFunction option of a TemplateBox to use Rule, not RuleDelayed. Compare:

System`Convert`CommonDump`ExpandTemplateBoxes @ TemplateBox[
    {"a"},
    "FOO",
    DisplayFunction :> (#&)
]

System`Convert`CommonDump`ExpandTemplateBoxes @ TemplateBox[
    {"a"}, 
    "FOO", 
    DisplayFunction -> (#&)
]

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

"a"

When RuleDelayed is used, the box structure generated by the DisplayFunction is ignored. So, modify your TemplateBox format to use Rule:

ClearAll[myFunction]
myFunction /: MakeBoxes[myFunction[a_, b_, c_], TraditionalForm] := 
    TemplateBox[
        {ToBoxes[a], ToBoxes[b], ToBoxes[c]}, "myFunctionTag", 
        DisplayFunction -> (SubsuperscriptBox[#1, #2, #3] &)
    ]

myFunction[h, 1, 2] // TeXForm

h_1^2

Note that I removed a superfluous HoldPattern in your definition.

$\endgroup$
1
  • $\begingroup$ Could you forward this issue somewhere? That is either is should accept RuleDelayed or the documentation of TemplateBox should stress that out. Currently the second example uses RuleDelayed for the DisplayFunction. $\endgroup$
    – Kuba
    Commented Aug 9, 2017 at 11:03

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.