Question 1:
What is the typesetting in Mathematica? What procedures does it include?
I think that this 2008 year MathGroup post by John Fultz completely answers this question, so I'll cite it here:
In version 6, the kernel has absolutely no involvement whatsoever in
generating the rendered image. The steps taken in displaying a
graphic in version 6 are very much like those used in displaying
non-graphical output. It works as follows:
1) The expression is evaluated, and ultimately produces something with
head Graphics[]
or Graphics3D[]
.
2) The resulting expression is passed through MakeBoxes
. MakeBoxes
has a set of rules which turns the graphics expression into the box
language which the front end uses to represent graphics. E.g.,
In[9]:= MakeBoxes[Graphics[{Point[{0, 0}]}], StandardForm]
Out[9]= GraphicsBox[{PointBox[{0, 0}]}]
Internally, we call this the "typeset" expression. It may be a little
weird thinking of graphics as being "typeset", but it's fundamentally
the same operation which happens for typesetting (which has worked
this way for 11 years), so I'll use the term.
3) The resulting typeset expression is sent via MathLink to the front
end.
4) The front end parses the typeset expression and creates internal
objects which generally have a one-to-one correspondence to the
typeset expression.
5) The front end renders the internal objects.
In version 6, the front end, and only the front end can render
graphics (unless you use the legacy PostScript scheme via
<<Version5`Graphics`
, in which the kernel does the hard job of
rendering the graphic to a simple subset of PostScript, and the FE
has the considerably easier job of merely rendering the PostScript to
the screen).
Question 2:
But I don't know why this is done this way:
MakeBoxes @ Graphics[Disk[]]
(*GraphicsBox[DiskBox[{0, 0}]]*)
MakeBoxes @ Whatever[Disk[]] (*expected*)
(*RowBox[{"Whatever", "[", RowBox[{"Disk", "[", "]"}], "]"}]*)
This is because typesetting rules are applied in a chain where the choices of branches depend of the previous choices (which in the first place are determined by the parent Head
s). Citing the Documentation for MakeBoxes
(emphasis is mine):
MakeBoxes
is NOT automatically called on the results it generates.
This means that explicit MakeBoxes
calls must typically be inserted
into definitions that are given.
We can Trace
the typesetting and see what actually happens:
ExportString[
Trace[MakeBoxes@Graphics[Disk[]], Typeset`MakeBoxes, TraceInternal -> True], "Text"]
"{{{HoldForm[Typeset`MakeBoxes[Graphics[Disk[]], StandardForm, Graphics]],
HoldForm[Typeset`ReleaseHold[System`Dump`InheritAmbientSettings[
With[{System`Dump`boxes = Typeset`MakeBoxes[Disk[], StandardForm,
Graphics], System`Dump`options = System`Dump`GraphicsOptionsToBoxes[
{}, StandardForm, Graphics]}, GraphicsBox[System`Dump`boxes,
System`Dump`options]], Graphics]]],
{{{{HoldForm[Typeset`MakeBoxes[Disk[], StandardForm, Graphics]],
HoldForm[DiskBox[{0, 0}]]}}}}}}}"
From the above we see that when the Head
of expression is Graphics
the call to MakeBoxes
is redirected to Typeset`MakeBoxes
with Graphics
as the third argument. But without the head Graphics
there is no call to Typeset`MakeBoxes
and everything is handled by MakeBoxes
:
Trace[MakeBoxes@Whatever[Disk[]], TraceInternal -> True]
{HoldForm[MakeBoxes[Whatever[Disk[]]]],
{HoldForm[MakeBoxes[Whatever, StandardForm]], HoldForm["Whatever"]},
{HoldForm[MakeBoxes[Disk[], StandardForm]],
{HoldForm[MakeBoxes[Disk, StandardForm]], HoldForm["Disk"]},
HoldForm[RowBox[{"Disk", "[", "]"}]]},
HoldForm[RowBox[{"Whatever", "[", RowBox[{"Disk", "[", "]"}], "]"}]]}
Question 3:
Why this design choice? Couldn't Grid
, Graphics
just evaluate to GraphicsBox
? (what would allow Hold
to prevent rendering)
Of course such question should best be answered by the developers but I think that a part of the answer is already clear from the "Question 2" section: parsing of expression into BoxForms (i.e. typesetting) is not intended to be a 1-to-1 operation, interpretation of a language construct depends on its neighborhood (especially on the parent expression in which it is embedded). Of course it is already a design choice but from this choice follows that typesetting cannot be done via OwnValues
. And as Mr.Wizard correctly points out in his answer, it would be very inconvenient from practical point of view if the expressions given in the high-level Mathematica language would automatically evaluated into their low-level BoxForm representation during usual process of working with them in the WL. I'm also glad that the most of the time in the WL we work only with the short and predictable high-level representation. At the same time, the language allows to control the process of conversion into BoxForms if it is strictly needed and it is also easy to prevent rendering of Graphics
without loosing the ability to render it later, some ideas you can take from my shortInputForm
function and the original thread when the first version of this function was developed, and the MakeBoxesStop
function by Leonid Shifrin from this thread can also be of interest for you:
MakeBoxesStop[Graphics[Disk[]]]
Graphics[Disk[List[0, 0]]]
The InputField
issue
Except of confusion this makes working with
InputField[Dynamic@x, Hold[Expression]]
pointless. Because as soon as you type something with custom
MakeBoxes
rules you will have to retype that to edit.
The reason for this is that the contents of the input field is rendered in StandardForm
when the value of Dynamic
variable x
is changed (including the situation when you change it via the InputField
itself, i.e. by typing and pressing Enter).
As a simple workaround I can suggest to work with String
, then convert it into expression using MakeExpression
. You can include the syntax checking into InputField
for example as follows:
InputField[Dynamic@x, String, Background -> Dynamic[If[SyntaxQ@x, Yellow, Red]]]
Now for syntactically correct WL expressions the input field will become yellow, but for incorrect it will become red.
Another workaround is suggested by Karsten 7. in his (now deleted) answer: InputField
allows to work with raw boxes when the second argument is Boxes
. When working with raw boxes you keep the same predictable and stable behavior of the input field as in the case of working with string input but allowed to use 2D formatting, paste already rendered images and other objects. What is significant, the appearance of the input field won't change after you press Enter and hence you won't have to retype anything!
Grid[{{"InputField",
"Converted to HeldExpression in InputForm"}, {InputField[Dynamic[x], Boxes,
BaseStyle -> "Input"], Dynamic[InputForm@ToExpression[x, StandardForm, Hold]]}},
Frame -> All]

Graphics
is that it is an inert representation of graphics. Since version 6, it doesn't evaluate, it doesn't do anything, etc. It just represents graphics. The front end then can show it as text, but it can also show it as an image. Both are just ways to display the same Mathematica expressions. In StandardForm it shows it as an image and in InputForm as text. $\endgroup$Graphics
but whatever that has specific rules forMakeBoxes
. As I said, I understandRawBoxes@GraphicsBox[DiskBox[{0, 0}]]
is meant to be a picture. I just don't understand whyGraphics
,without evaluation, is converted toGraphicsBox
instead ofRowBox "Graphics" "[" ...
. I don't claim I'm right. Maybe I'm missing something, well obviously I am missing something, that's why there is a question. $\endgroup$MakeBoxes
still allows you to writeGraphicsBox
and see images without evaluation. So the behavior I'm talking about is nothing more but shortcut which generates problems. In my opinion, but still, I am rather asking for explanation than complaining :) $\endgroup$InputField
issue. I think it is worth to keep it as a partial answer demonstrating that the problem withInputField
resulting from the described design choices is not so severe as one can imagine... $\endgroup$