In a recent SO question three different answers were supplied each using a different method of preventing the evaluation of the Equal[]
expression. They were
Defer[]
Unevaluated[]
HoldForm[]
Sometimes I still have trouble choosing between these options (and judging by answers to the before mentioned question, the choice isn't always clear for other people either). Can someone write a clear exposition on the use of these three methods?
There are three other wrappers
Hold[]
,
HoldPattern[]
,
HoldComplete[]
,
and the various Attributes
for functions
HoldAll
, HoldFirst
, HoldRest
and the numeric versions NHold*
that can also be discussed if you wish!
I just noticed that this is basically a repeat of the old question (which I had already upvoted, just forgotten...). The accepted answer linked to this talk at the 1999 Mathematica Developer Conference, which doesn't discuss Defer
since it is "New in 6". Defer
is more closely linked to the frontend than the other evaluation control mechanisms. It is used to create an unevaluated output that will be evaluated if supplied in and Input
expression. To quote the Documentation Center:
Defer[expr] returns an object which remains unchanged until it is explicitly supplied as Mathematica input, and evaluated using Shift+Enter, Evaluate in Place, etc.
To stop this computation, first select its cell bracket: Then select Abort Evaluation from the Evaluation menu: The Wolfram System then outputs $Aborted: If Abort Evaluation does not succeed in stopping the computation, you can do so by quitting the active kernel.
Hold has attribute HoldAll and performs no operation on its arguments. Hold is removed by ReleaseHold. » Hold[e1,e2,…] maintains a sequence of unevaluated expressions to which a function can be applied using Apply.
Re-launch Mathematica, and you should see F8 next to the Evaluate Notebook command.
Not touching Defer
, since I did not work much with it and feel that in any given case its behavior can be reproduced by other mentioned wrappers, and discussing Hold
instead on HoldForm
(the difference is really in the way they are printed), here is the link to a mathgroup post where I gave a rather extensive explanation of differences between Hold
and Unevaluated
, including differences in usage and in the evaluation process (my second and third posts in particular).
To put the long story short, Hold
is used to preserve an expression unevaluated in between several evaluations (for indefinite time, until we need it), is a visible wrapper in the sense that say Depth[Hold[{1,2,3}]]
is not the same as Depth[{1,2,3}]
(this is of course a consequence of evaluation), and is generally nothing special - just a wrapper with HoldAll
attribute like any other, except being an "official" holding wrapper and being integrated much better with the rest of the system, since many system functions use or expect it.
OTOH, Unevaluated[expr]
is used to temporarily, just once, make up for a missing Hold* attribute for a function enclosing expression expr
. While resulting in behavior which would require this enclosing function to hold expr
as if it had Hold*
- attribute, Unevaluated
belongs to the argument, and works only once, for a single evaluation, since it gets stripped in the process. Also, because it gets stripped, it often is invisible for the surrounding wrappers, unlike Hold
. Finally, it is one of a very few "magic symbols", along with Sequence
and Evaluate
- these are deeply wired into the system and can not be easily replicated or blocked, unlike Hold
- in that sense, Unevaluated
is more fundamental.
HoldComplete
is used when one wants to prevent certain stages of evaluation process, which Hold
does not prevent. This includes splicing sequences, for example:
In[25]:= {Hold[Sequence[1, 2]], HoldComplete[Sequence[1, 2]]}
Out[25]= {Hold[1, 2], HoldComplete[Sequence[1, 2]]},
search for UpValues
, for example
In[26]:=
ClearAll[f];
f /: Hold[f[x_]] := f[x];
f[x_] := x^2;
In[29]:= {Hold[f[5]], HoldComplete[f[5]]},
Out[29]= {25, HoldComplete[f[5]]}
and immunity to Evaluate
:
In[33]:=
ClearAll[f];
f[x_] := x^2;
In[35]:= {Hold[Evaluate[f[5]]], HoldComplete[Evaluate[f[5]]]}
Out[35]= {Hold[25], HoldComplete[Evaluate[f[5]]]}
In other words, it is used when you want to prevent any evaluation of the expression inside, whatsoever. Like Hold
, HoldComplete
is nothing special in the sense that it is just an "official" wrapper with HoldAllComplete
attribute, and you can make your own which would behave similarly.
Finally, HoldPattern
is a normal (usual) head with HoldAll
attribute for the purposes of evaluation, but its magic shows in the pattern-matching: it is invisible to the pattern-matcher, and is very important ingredient of the language since it allows pattern-matcher to be consistent with the evaluation process. Whenever there is a danger that the pattern in some rule may evaluate, HoldPattern
can be used to ensure that this won't happen, while the pattern remains the same for the pattern-matcher. One thing I'd stress here that this is the only purpose for it. Often people use it also as an escape mechanism for the pattern-matcher, where Verbatim
must be used instead. This works, but is conceptually wrong.
One very good account on evaluation process and all these things is a book of David Wagner, Power programming with Mathematica - the kernel, which was written in 1996 for version 3, but most if not all of the discussion there remains valid today. It is out of print alas, but you might have some luck on Amazon (as I had a few years ago).
Leonid Shifrin's answer is quite nice, but I wanted to touch on Defer
, which is really useful for only one thing. In some instances, it's nice to be able to directly construct expressions that won't be evaluated, but that a user will be able to easily edit; the basic example for this kind of behavior is button palettes that you can use to insert expressions or expression templates into input cells which the user can then edit as needed. This isn't the only way to do this, and for some more sophisticated applications you'll need to get into the hairy world MakeBoxes
, but for the basics Defer
will serve nicely.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With