11
$\begingroup$

Say I want to define a custom graphical representation for my function foo. I can do this using MakeBoxes as in the following:

foo /: MakeBoxes[foo[x_, y_], StandardForm] := ToBoxes @ Graphics[{
    Point@{x, y}
  }, Frame -> True, PlotRange -> {{-2, 2}, {-2, 2}}
]

so that evaluating foo[1, 1.5] produces a Graphics object accordingly. This also works consistently if another function foobar is defined to act on a foo object, like in

foobar[foo[x_, y_]] := (Print["Matched"]; x + y)

There is another way to achieve the same result, which is using Interpretation. I could define foo2 as

foo2[x_, y_] := Interpretation[
    Graphics[{
        Point@{x, y}
      }, Frame -> True, PlotRange -> {{-2, 2}, {-2, 2}}
    ],
    foo2[x, y]
]

This produces the same result, and works consistently when defining another function like

foobar2[foo2[x_, y_]] := (Print["Matched"]; x + y)

I (vaguely) know that Interpretation produces an InterpretationBox, so I'm guessing there should be fundamental differences between this and the result of using MakeBoxes, but I don't know what they are exactly. What are the circumstances in which one function should be preferred with respect to the other? And what the intrinsic differences?

$\endgroup$
  • $\begingroup$ I completely rewrote the answer in the hope that it will be clearer and more educational. $\endgroup$ – Szabolcs Feb 21 '17 at 14:29
9
$\begingroup$

Point of conversion

A large and perhaps key difference is that MakeBoxes (foo) only transforms the expression into the expanded form when it is converted to Box form. It's FullForm remains unchanged.

foo[1, 0.3] // InputForm
foo[1, 0.3`]

This means that you can operate upon the expression in every standard way without thought to a hidden internal format.

Sin /@ foo[1, 0.3`];
%[[2]]
0.29552

Interpretation (foo2) does not allow this:

Sin /@ foo2[1, 0.3`];
%[[2]]

enter image description here

The cause:

Sin /@ foo2[1, 0.3`] // InputForm
Interpretation[
 Sin[Graphics[{Point[{1, 0.3}]}, Frame -> True, PlotRange -> {{-2, 2}, {-2, 2}}]], 
 Sin[foo2[1, 0.3]]]

Held expressions

Another difference manifests when these expressions are wrapped in Hold constructs. Because MakeBoxes works outside the standard evaluation sequence the graphic still displays. foo2 however must evaluate before Interpretation is even part of the expression.

HoldForm[ foo[1, 0.3] ]

HoldForm[ foo2[1, 0.3] ]

enter image description here

Related to this point: Prevent graphics render inside held expression

$\endgroup$
8
$\begingroup$

Assuming that you want to create a special display form for foo that can be used in all contexts, you should use neither of these solutions. Why?

  • MakeBoxes controls how foo will be formatted. This is part of what you want. But the way you used it, the formatting is one-way. It will not be possible to convert the already formatted output as a foo expression. For example, if you edit the output cell directly, or by copying the output and paste it elsewhere, it will behave as Graphics and not as foo.

  • Interpretation is meant for typesetting only, and cannot be used in normal calculations. Interpreation["two", 2] will format in a special way so that if you copy the formatted output, and paste it elsewhere, it will look like "two", but it will behave like 2. However, if you do not format it inside of a notebook and then copy it, it will not be possible to use it as a substitute for 2. For example, Head@Interpretation["two", 2] will return Interpretation and not Integer. Thus, before Interpretation will start behaving equivalently to its second argument in computations, you must display it, then copy the displayed form.

What should you use then?

I suggest you use a specific combination of MakeBoxes and Interpretation that I presented here. This will work both ways:

  • It formats the expression in a graphical way
  • The formatted expression can be turned back into a computable expression (with head foo)

Example:

MakeBoxes[expr : foo3[x_, y_], StandardForm | TraditionalForm] := 
 ToBoxes@Interpretation[
   Graphics[{Point@{x, y}}, Frame -> True, PlotRange -> {{-2, 2}, {-2, 2}}], 
   expr
 ]

Under the hood, this creates an InterpretationBox. InterpretationBox is a special box form that already contains the expression it represents. Thus you do not need to create an explicit back-conversion rule using MakeExpression.

The above could also be written as

MakeBoxes[expr : foo3[x_, y_], StandardForm | TraditionalForm] := 
  With[{boxes = ToBoxes@Graphics[{Point@{x, y}}, Frame -> True, PlotRange -> {{-2, 2}, {-2, 2}}]}, 
    InterpretationBox[boxes, expr]
  ]

This form will sometimes give more flexibility.


With foo3 you can do the following:

enter image description here

Neither of the two approaches you describe (foo and foo2) will behave this way.

$\endgroup$
  • $\begingroup$ Related: (4112299) $\endgroup$ – Mr.Wizard Feb 19 '17 at 16:07
  • 1
    $\begingroup$ @Mr.Wizard Maybe tomorrow, I should be doing something else right now ... will log off. Perhaps OP can comment is this is useful at all and I will edit or delete the answer tomorrow. $\endgroup$ – Szabolcs Feb 19 '17 at 16:10
  • 1
    $\begingroup$ @Mr.Wizard I see your point, but perhaps the question poses a false dichotomy. The question asks whether to use MakeBoxes or Interpretation. But the two are normally used together, as illustrated by this response. I suggest that Interpretation does not have much use outside of typesetting because the wrapper just "gets in the way". (Incidentally, I tend to use higher level UI constructs like Interpretation over lower level box constructs like InterpretationBox, but that is just a matter of taste.) $\endgroup$ – WReach Feb 19 '17 at 16:30
  • 1
    $\begingroup$ @Mr.Wizard I rewrote the answer, hope it's clearer. $\endgroup$ – Szabolcs Feb 21 '17 at 14:28
  • 1
    $\begingroup$ @glS Yes, you could put it that way. To be honest, I never really understood what Interpretation was good for in practice, when used on its own (without MakeBoxes). But I am sure that there are some good uses that I have not thought of. $\endgroup$ – Szabolcs Feb 21 '17 at 15:18

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.