I want to format results from Reduce
using the $\cup$ symbol instead of the $\lor$ symbol. For example, Reduce[x^2 > 4, x, Reals]
produces $x<-2\lor x>2$ while I would like it to produce $x<-2\cup x>2$.
My current solution is to add the head xO
to use in place of the Or
head and associate the appropriate formatting with the xO
head using MakeBoxes
.
xO /: MakeBoxes[xO[x_, y_], form_] :=
RowBox[{MakeBoxes[x, form], "\[Union]", MakeBoxes[y, form]}];
When I want to invoke the special formatting, I simply substitute xO
for Or
.
Reduce[x^2 > 4, x, Reals] /. Or -> xO
This produces the desired result of $(x<-2)\cup (x>2)$. I am feeling like a master bit-twiddler at this point.
Of course, my next test case didn't work.
Reduce[x^3 + 2 x^2 - x - 2 == 0] /. Or -> xO
(* xO(x==-2,x==-1,x==1) *)
My MakeBoxes[xO[x_, y_]]
definition above does not match the case when xO
has three arguments. I added the following to limp along a little further.
xO /: MakeBoxes[xO[x_, y_, z_], form_] :=
RowBox[{MakeBoxes[x, form], "\[Union]", MakeBoxes[y, form], "\[Union]", MakeBoxes[z, form]}];
This works for three arguments, but is clearly not a robust solution. What is the general method for an n-ary function?
I tried several variations of the following:
xO /: MakeBoxes[xO[x_, y__], form_] :=
RowBox[{MakeBoxes[x, form], "\[Union]", MakeBoxes[y, form]}];
which produced the error:
MakeBoxes::argt: "MakeBoxes called with 3 arguments; 1 or 2 arguments are expected"
when applied to the Reduce[x^3 + 2 x^2 - x - 2 == 0] /. Or -> xO
test case.
I am probably missing something obvious. Any ideas?
Answer
You were almost there. You just need to use the multiple-argument pattern, and generalize your code accordingly to create the internals of RowBox
programmatically:
xO /: MakeBoxes[xO[x___], form_] :=
RowBox[
Riffle[
Map[MakeBoxes[#, form] &, {x}],
"\[Union]"
]
]
Note however that the above implementation leaks evaluation. It may or may not be a problem, but for example here:
x = 1;
xO[x == 1, x > 1, x < 1]
one may argue that the desired result should not be sensitive to the possible global values that x
may have, so the result:
(* True \[Union] False \[Union] False *)
may be unsatisfacory. Thus, here is a more careful version:
ClearAll[xO];
SetAttributes[xO, HoldAllComplete];
xO /: MakeBoxes[xO[x___], form_] :=
RowBox@Riffle[
List @@ Replace[
HoldComplete[x],
elem_ :> With[{eval = MakeBoxes[elem, form]}, eval /; True],
{1}
],
"\[Union]"
]
which now gives
xO[x == 1, x > 1, x < 1]
(* x == 1 \[Union] x > 1 \[Union] x < 1 *)
Comments
Post a Comment