[Date Index]
[Thread Index]
[Author Index]
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.
Prev by Date:
**Re: Re: More /.{I->-1} craziness**
Next by Date:
**Re: Re: simple nest**
Previous by thread:
**What is the difference Between MakeBoxes and ToBoxes**
Next by thread:
**Re: What is the difference Between MakeBoxes and ToBoxes**
| |