7
$\begingroup$

Inspired by the @ybeltukov 's answer to this question, if I have the following polynomial

poly = a^2 + (a^2 + b^2 - c^2)*x + b^2*x^2; var = x; 

this generates boxes out of a polynomial to be displayed in canonical order:

MakeBoxes[+##] & @@ (var^#1[[1]] #2 & @@@ CoefficientRules[poly, var]) % // DisplayForm // TraditionalForm 

$b^2 x^2 + (a^2 +b^2 -c^2)x + a^2$

But if I use the same construction to define MakeBoxes for my function mypoly in TraditionalForm

MakeBoxes[mypoly[poly_, var_], TraditionalForm] := MakeBoxes[+##] & @@ (var^#1[[1]] #2 & @@@ CoefficientRules[poly, var]) 

Then asking it to display in TraditionalForm

mypoly[a^2 + x^2 b^2 + x (a^2 + b^2 - c^2), x] // TraditionalForm 

does not yield the correct order:

$x(a^2 +b^2 -c^2) + a^2 +b^2 x^2$

Why? and what can I do to get the right order?

$\endgroup$
6
  • 2
    $\begingroup$ not really an answer, but if you put an HoldForm around the +## in MakeBoxes it works: MakeBoxes[mypoly[poly_, var_], TraditionalForm] := MakeBoxes[HoldForm[+##]] & @@ (var^#1[[1]] #2 & @@@ CoefficientRules[poly, var]) $\endgroup$ Commented Aug 13, 2016 at 15:03
  • $\begingroup$ @gIS but it is an answer. I'll try it out as soon as I get my hands on Mathematica. $\endgroup$ Commented Aug 13, 2016 at 17:00
  • 1
    $\begingroup$ well, I mean, it solves the problem but as the question was about why this happens, I'm not really able to answer that! Clearly something about the order things are evaluated but I was not able to pinpoint it exactly. Something interesting is that adding that HoldForm changes the output only in that it wraps the resulting expression into a TagBox, which again I'm not really sure what it does (the docs say that TagBox somehow helps "guiding the interpretation of the boxes") $\endgroup$ Commented Aug 13, 2016 at 17:11
  • $\begingroup$ I had no idea you could do +##, nice trick. $\endgroup$ Commented Aug 19, 2016 at 13:31
  • $\begingroup$ @masterxilo Thanks, but it's actually from ybeltukov's answer in the link given at top. $\endgroup$ Commented Aug 19, 2016 at 13:43

1 Answer 1

6
$\begingroup$

Interesting question. Building on comments by glS It appears that HoldForm is treated specially by (conversion to) TraditionalForm, whereas a normal hold attribute does not prevent reordering. This is not exactly surprising considering that formatting rules do not directly respect hold attributes. (See Returning an unevaluated expression with values substituted in.)

Here is a concise example:

{HoldForm[b + a^2], Defer[b + a^2], HoldComplete[b + a^2]} // TraditionalForm 

enter image description here

Note that neither Defer nor HoldComplete prevent this reordering. So while MakeBoxes has HoldAllComplete this is insufficient to preserve order.

Further, Box form is itself vulnerable to reordering by TraditionalForm:

MakeBoxes[b + a^2] % // TraditionalForm // DisplayForm 
RowBox[{"b", "+", SuperscriptBox["a", "2"]}] a^2 + b 

Note that the RowBox is in the correct order but the second line still alters its order.

One finds that HoldForm becomes a TagBox upon box conversion. Interestingly it seems that an arbitrary TagBox also prevents this reordering:

TagBox[RowBox[{"b", "+", SuperscriptBox["a", "2"]}], foo] // TraditionalForm // DisplayForm 
b + a^2 
MakeBoxes[Annotation[b + a^2]] % // TraditionalForm // DisplayForm 
TagBox[RowBox[{b, +, SuperscriptBox[a, 2]}], #1 &] b + a^2 

In any case it seems that including HoldForm is the simplest solution. Here is an alternative formulation using Collect for your consideration:

MakeBoxes[mypoly[poly_, var_], TraditionalForm] := ToBoxes @ Collect[poly, var, # &, HoldForm[+##] ~Reverse~ {2} &] 
$\endgroup$

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.