Assuming each odd line is input I would like the even lines to be the output of the following lines.

enter image description here

In the above the Graphics are inside Hold/HoldForm therefore IMO it doesn't make sense to have Mathematica try and render such expressions. For example Hold[Graphics[{Red, Circle[]}]] throws an error because built in colors don't get replaced.

How might I prevent Graphics from being rendered and instead print the Graphics code?

The following code works at reassigning Graphics inside Hold/HoldForm, but it prints something like Graphics[{Circle[{0, 0}]}] without the HoldForm/Hold.

Graphics /: HoldForm[Graphics[x___]] := (
Graphics /: Hold[Graphics[x___]] := (

Ideally the code should be generalized to work with irregular constructs like HoldForm["a",Graphics[{Circle[{0, 0}]}]]. More importantly, how might you insure HoldComplete doesn't render Graphics either. As rm-rf pointed out the Villegas–Gayley trick will likely be needed.

Simplifying John Fultz's answer slightly, you get the following:

   # /: MakeBoxes[#[expr_], fmt : StandardForm | TraditionalForm] := 
    Block[{Graphics, Graphics3D},
     RowBox[{ToString[#], "[", MakeBoxes[expr, fmt], "]"}]
   ) &, {Hold, HoldForm, HoldComplete}
  • 1
    $\begingroup$ This is not exactly what you want but: ToString[#, InputForm] &@Graphics[{Red, Circle[]}] $\endgroup$
    – Kuba
    Commented Sep 14, 2013 at 0:32
  • $\begingroup$ Also not exactly what you want, use graphics instead of Graphics and replace when it's time to render. $\endgroup$
    – ssch
    Commented Sep 14, 2013 at 0:39
  • 1
    $\begingroup$ I don't think you're going to get anywhere by monkeying with Graphics. As I see it, solving your problem requires changing the way the fonte end's output printer works. I don't have a clue on to do that. $\endgroup$
    – m_goldberg
    Commented Sep 14, 2013 at 1:50
  • 1
    $\begingroup$ Possibly related: Making customized InputForm and ShortInputForm. $\endgroup$ Commented Sep 15, 2013 at 1:36
  • 1
    $\begingroup$ Also closely related: "Conversion of expressions by the FrontEnd." $\endgroup$ Commented Jan 2, 2014 at 18:22

5 Answers 5


John Fultz alluded to using the Villegas-Gayley pattern. Since I believe that is the correct approach to this problem here is an implementation.

mk : MakeBoxes[(Hold | HoldForm | HoldComplete | HoldPattern)[__], _] :=
  Block[{$hldGfx = True, Graphics, Graphics3D}, mk] /; ! TrueQ[$hldGfx]

I included HoldPattern to complete the Hold functions. This now works at any depth:

Hold[1, 2, foo[3, Graphics[{Green, Circle[]}], 4], 5]
Hold[1, 2, foo[3, Graphics[{Green, Circle[]}], 4], 5]


Jacob Akkerboom questioned the overhead of this general rule attached to MakeBoxes. To test this I converted a large expression to Box form using ToBoxes (which calls MakeBoxes), and timed the operation with and without this definition as well as several alternatives. Here are the results (in version 7). Each test was performed in a fresh kernel, using this code:

expr = Expand[(1 + x + y)^4 (2 - z)^5 (q - 7 - a)^7 (b + r - 4)^6];
ToBoxes[expr] // AbsoluteTiming // First
  • Raw (no additional MakeBoxes rules): 0.7940454
  • Alternatives DownValue on MakeBoxes: 1.1030631
  • Four individual DownValues on MakeBoxes: 1.4690841
  • Four UpValues on Hold* functions: 0.7890451

(Incidentally, use of the Notations Package causes far larger overhead; the timing performed in my standard configuration was 3.5652039 seconds.)

It appears that Jacob's concern is valid as the overhead of my method above is significant, though not extreme. I usually attach rules to MakeBoxes to avoid having to Unprotect system Symbols but I may have to reconsider that practice. If you prefer unprotecting system Symbols to the overhead you may use this:

  Unprotect @ #;
  mk : MakeBoxes[Blank[#], _] /; ! TrueQ[$hldGfx] ^:= 
    Block[{$hldGfx = True, Graphics, Graphics3D}, mk];
  Protect @ #
) & ~Scan~ {Hold, HoldForm, HoldComplete, HoldPattern}
  • $\begingroup$ Thank you! Now there are 2 good answers. I don't love the idea of changing the right answer after so long, but this is definitely the right/better/more complete answer. $\endgroup$
    – William
    Commented Jan 1, 2014 at 22:55
  • $\begingroup$ @Liam You're welcome, and thanks for the Accept. $\endgroup$
    – Mr.Wizard
    Commented Jan 2, 2014 at 2:50
  • $\begingroup$ @Liam I simplified my code; please take a look and let me know if you run into any problems. $\endgroup$
    – Mr.Wizard
    Commented Jan 2, 2014 at 6:21
  • $\begingroup$ @Mr.Wizard I suppose that this definition will slow down MakeBoxes quite a bit. When you call MakeBoxes[whatever[b]], I imagine it will at least have to test something like Hold === whatever, HoldForm === whatever etc. I think the definition will be associated with MakeBoxes. Also I suspect MakeBoxes is used once whenever you type a character in the front end. What are your thoughts on this? $\endgroup$ Commented Jan 2, 2014 at 10:15
  • $\begingroup$ @Jacob please see update $\endgroup$
    – Mr.Wizard
    Commented Jan 2, 2014 at 17:51

Recall that the rendering of Graphics has nothing to do with evaluation. It is done entirely in typesetting. And therefore, a robust solution will treat this as a problem of typesetting, and not as a problem of evaluation.

Once you frame the problem properly, the solution is fairly straightforward. What you want to do is to change the typesetting of Hold (and friends). Take a look at this:

Hold /: MakeBoxes[Hold[expr_], fmt : StandardForm | TraditionalForm] :=
  Block[{Graphics, Graphics3D}, Unprotect[Graphics, Graphics3D]; 
  Clear[Graphics, Graphics3D]; 
  RowBox[{"Hold", "[", MakeBoxes[expr, fmt], "]"}]]

Fortunately, Hold (and HoldForm and HoldComplete) has no typesetting rules directly attached to it that you're fighting, which you can determine using FormatValues[Hold]. But Graphics and Graphics3D do; it's how typesetting of graphics works at all. We want to suppress those rules, but only within the typesetting of Hold. So we use Block to contain the damage we're about to do to the Graphics and Graphics3D symbols, and then use Clear to clear them. From there on out, we let MakeBoxes do what it would normally do.

Note that this example cheats a bit; it only works if you pass one argument to Hold. I did that for purpose of code simplicity and illustration. To make the formatting rules work properly for Hold[expr___], I would have to write multiple and more sophisticated rules, or I would have to use the Villegas-Gayley trick.

Edit: As came up in the comment discussion, it really isn't necessary to Unprotect and Clear the symbols Graphics and Graphics3D, as Block is effectively doing that already. I've considered editing the code to make it shorter/simpler, but perhaps the existing code is clearer for people who don't fully understand how Block works (and, public confession here, while I understand Block scoping, I had just plumb forgotten how Block initializes variables, so this more an oversight on my part than a planned teaching moment).

  • 3
    $\begingroup$ Nice explanation and solution,+1. It is not clear to me however, why Unprotect and Clear are needed, since Block automatically clears all symbol's definitions and attributes (in contrast to Internal`InheritedBlock). $\endgroup$ Commented Sep 14, 2013 at 13:34
  • 2
    $\begingroup$ @LeonidShifrin I think it was simply John Fultz kind attempt to make it clearer to what is exactly going on. They way it is currently written makes perfect sense(at least to me). Additionally if I don't understand the differences between With,Module, and Block/Internal`InheritedBlock. How do you prevent evaluation of a function? Well by Removing and Clearing it of course. $\endgroup$
    – William
    Commented Sep 14, 2013 at 14:55
  • 3
    $\begingroup$ Actually, believe it or not, there are limits to my knowledge of Mathematica, and for some reason, it didn't occur to me to see if Block would automatically clear a Protected System symbol. I appreciate @Liam reading the benefit of hidden wisdom into my answer, though! :) And, in fact, that response gives me pause about editing the answer to shorten the code. $\endgroup$
    – John Fultz
    Commented Sep 14, 2013 at 16:36
  • 1
    $\begingroup$ In reply to your last comment: Yes, you are correct. I was hoping to clear any confusion when I was comparing AtomQ[Graph[...]] with AtomQ[Unevaluated[Graph[...]]], where the former gives True and the latter gives False. Unevaluated is not responsible for the difference :) $\endgroup$ Commented Jan 2, 2014 at 18:43
  • 1
    $\begingroup$ @AlexeyPopkov in reply to your first comment: ah yes this is precisely the point :). If you "Set" gr = Graph[...], then the expression with head Graph is evaluated outside the Block. Note that blocking Graph later will have no effect as the expression with head Graph is already converted into an atomic expression. Even if it's Head is still Graph, it is not a "proper head". Anyway the function Graph generates this atomic expression. If you evaluate gr inside the Block, then the expression with head Graph is not converted into an atom, as Graph has no special meaning. $\endgroup$ Commented Jan 2, 2014 at 18:48

This is not an answer but an extended comment.

Regarding your assertion

This occurs because although the front end attempts to render the Graphics element the internal code won't replace Directives inside of a Held expression.

This is not the case. Consider

Hold[Graphics[{RGBColor[1, 0, 0], Thick, Circle[]}]]



 With[{red = Red}, Hold[Graphics[{red, Circle[]}]]]


So the error message comes from using the built-in symbol Red and not from the front end doing anything funny with directives.

  • $\begingroup$ Is Color Directives more appropriate then? Seems to be an issue for all colors. $\endgroup$
    – William
    Commented Sep 14, 2013 at 1:59
  • $\begingroup$ @Liam. RGBColor[1, 0, 0] is a color directive; Red,Green, Blue, etc. are not. $\endgroup$
    – m_goldberg
    Commented Sep 14, 2013 at 2:02
  • 1
    $\begingroup$ That's fair although I find it odd that the colors are listed under guide/GraphicsDirectives Graphics Directives in the docs. Would simply colors be an appropriate name? $\endgroup$
    – William
    Commented Sep 14, 2013 at 2:04
  • 1
    $\begingroup$ @Liam. I regard that to be an error in the docs. They are symbols that evaluate to graphic directives, but of course not inside Hold. $\endgroup$
    – m_goldberg
    Commented Sep 14, 2013 at 2:08
  • $\begingroup$ @Liam. You might well ask "Why then does Thick work?" I wonder about that myself. $\endgroup$
    – m_goldberg
    Commented Sep 14, 2013 at 2:12

In M11+, if you are willing to create a new Hold* wrapper, you could define:


MakeBoxes[HoldFormatting[expr_], StandardForm]^:=MakeBoxes[DisableFormatting[expr]]


HoldFormatting[{1+1, Graphics[{Green,Circle[]}]}]

{1 + 1, Graphics[{Green, Circle[]}]}


If you take @JohnFultz 's initial comment

Recall that the rendering of Graphics has nothing to do with evaluation. It is done entirely in typesetting. And therefore, a robust solution will treat this as a problem of typesetting, and not as a problem of evaluation.

then I would ask, why are you using Hold in the first place? Hold is for the kernel, not for the front-end. I tried your Hold[Graphics[{Red, Circle[]}]] and saw the error too; but look at the expression inside the notebook (Cmd-Shift-E on Mac)

 RowBox[{"Hold", "[", 
  GraphicsBox[{Red, CircleBox[{0, 0}]}], "]"}]], "Output",

The front-end wraps all in a Cell (content in a notebook lives inside cells). Cell contains boxes, and boxes are generated from the expression. It also replaced Graphics by GraphicsBox and Circle by CircleBox. Red is unknown to the front-end as it is.


Graphics[{Red, Circle[]}] // InputForm

and you see

Graphics[{RGBColor[1, 0, 0], Circle[{0, 0}]}]

Funny enough, it seems the kernel knows about Red and Circle's default and the front-end gets those symbols evaluated. Graphics gets passed as is, although -I bet- it must have some rules in the kernel that allow the front-end to get a clearer command.

If you do

Hold[Graphics[{Red, Circle[]}]] // InputForm

you see in the front-end

Hold[Graphics[{Red, Circle[]}]]

The kernel didn't attempt to resolve the expression at all - as expected.

I am far from being an expert on these things, but I think the central issue is trying to use Hold in the front-end, which as we can see, has no effect. The front-end has its own transformation rules, from the expressions it gets from the kernel to the cell and box objects it needs to display.

The good -and confusing- thing is that the kernel can manipulate those symbols too (Cell, boxes, InputForm, etc), so one can return formatted expressions to the front-end and this is how (IMHO) the problem should be approached.

So a very simple approach is just to use InputForm as suggested above.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.