Re: What is the difference Between MakeBoxes and ToBoxes

*To*: mathgroup at smc.vnet.net*Subject*: [mg106729] Re: [mg106684] What is the difference Between MakeBoxes and ToBoxes*From*: John Fultz <jfultz at wolfram.com>*Date*: Fri, 22 Jan 2010 05:36:52 -0500 (EST)*Reply-to*: jfultz at wolfram.com

On Thu, 21 Jan 2010 04:51:36 -0500 (EST), George wrote: > May you please advise me what is the difference between "ToBoxes" and > "MakeBoxes"? I read in Mathematica manual and unerstood that the only > differerence is that "MakeBoxes" generates boxes without evaluation of > input...So is that all the difference? > > I saw also some examples where on lhs is "MakeBoxes" and on rhs is > "ToBoxes" when I just changed "MakeBoxes" into "ToBoxes" (and vice > versa) the Mathematica gave me some errors.... So could anybody > explain me with a simple practical example with explanation? > > Thank you very much > George Yes, partly that MakeBoxes works with held (unevaluated) expressions. Also, typesetting rules are expressed in as MakeBoxes rules, not ToBoxes rules, precisely because typesetting is an operation that generally wants to avoid evaluation as much as possible. These points are not trivial issues. Here are some examples of the differences. First, notice this example, which doesn't work. In[1]:= myop /: ToBoxes[myop[x_, y_, z_], StandardForm] := SubsuperscriptBox[ToBoxes[x, StandardForm], ToBoxes[y, StandardForm], ToBoxes[z, StandardForm]] In[2]:= myop[a, b, c] Out[2]= myop[a, b, c] Why? Because the parent typesetting process called MakeBoxes, not ToBoxes (as documented, ToBoxes observes MakeBoxes, but not the other way around). The rule didn't match. Okay, let's make the rule match using MakeBoxes on the lhs, but ToBoxes on the rhs... In[3]:= myop /: MakeBoxes[myop[x_, y_, z_], StandardForm] := SubsuperscriptBox[ToBoxes[x, StandardForm], ToBoxes[y, StandardForm], ToBoxes[z, StandardForm]] In[4]:= Hold[myop[1 + 1, 2, 3]] Out[4]= Hold[\!\*SubsuperscriptBox[\(2\), \(2\), \(3\)]] Now we see a different problem. The rule matched because we used MakeBoxes on the left. But we have a Hold[] wrapper, which was supposed to stop the evaluation of '1+1' into '2'. But typesetting doesn't know anything about the environment a thing was evaluated in. And so, by allowing ToBoxes a crack at this in the MakeBoxes rules, we've destroyed the evaluation order. So evaluation is really very, very important. Here is the correct rule... In[5]:= myop /: MakeBoxes[myop[x_, y_, z_], StandardForm] := SubsuperscriptBox[MakeBoxes[x, StandardForm], MakeBoxes[y, StandardForm], MakeBoxes[z, StandardForm]] In[6]:= Hold[myop[1 + 1, 2, 3]] Out[6]= Hold[\!\*SubsuperscriptBox[\(1 + 1\), \(2\), \(3\)]] Setting aside for the moment that my example is a little silly, this has now done the right thing. However, when you're not writing typesetting rules, but you simply want to work with boxes, dealing with held evaluation can be very cumbersome. You have to be constantly on the watch for how Mathematica is replacing symbols. E.g., In[7]:= Module[{expr = x^2}, CellPrint[Cell[BoxData[MakeBoxes[expr, StandardForm]]]]] expr$532 Module[] lexically replaces expr with the module variable expr$532 (in this case), but the resolved value requires evaluation. Since MakeBoxes holds its argument, there are only two convenient ways around this...either use a fully lexical scoping construct like With[], or don't use MakeBoxes. In[8]:= Module[{expr = x^2}, CellPrint[Cell[BoxData[ToBoxes[expr, StandardForm]]]]] x^2 Sincerely, John Fultz jfultz at wolfram.com User Interface Group Wolfram Research, Inc.