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$
  • 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$ – glS Aug 13 '16 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$ – QuantumDot Aug 13 '16 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$ – glS Aug 13 '16 at 17:11
  • $\begingroup$ I had no idea you could do +##, nice trick. $\endgroup$ – masterxilo Aug 19 '16 at 13:31
  • $\begingroup$ @masterxilo Thanks, but it's actually from ybeltukov's answer in the link given at top. $\endgroup$ – QuantumDot Aug 19 '16 at 13:43
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$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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