[Graphics:Images/index_gr_1.gif]

Robby Villegas
Wolfram Research

Abstract:

Most experienced Mathematica programmers will eventually encounter tasks or applications in which they need to manipulate expressions without letting them evaluate. For instance, typesetting and interpretation rules, debugging programs, code analysis tools, and constructing code on the fly at run time are all areas of programming that require careful control of evaluation.  Since Mathematica automatically evaluates arguments and return values of functions, building up a result without exposing intermediate stages of work to the evaluator requires subtle techniques that even seasoned Mathematica programmers sometimes find elusive. In this tutorial, I will demonstrate situations in which evaluation control is important, pointing out common pitfalls and providing useful tools and techniques along the way.

[Graphics:Images/index_gr_2.gif]

An Introduction to demystify scary things

The overarching evaluator
An unevaluated expression is just an expression, a tree structure like anything else.
Simple uses of Unevaluated
Unevaluated must be wrapper before argument evaluation, not after, else it isn't stripped

Several specific techniques

Manipulations

Use Function[] to make a temporary holding version of a function
Replace is one of these easiest methods for transforming a structure, and it's sort of "visual programming", making it very clear to the reader what is happening.
Function and With can stuff values into any expression, including held ones.
Build up the arguments inside of Hold, then apply the function at the end
Construct a held result from parts
Wrap everything in a holding wrapper, do your manipulations, then finish with ReleaseHold.
Replace function names with temporary dummy symbols
Use Block to temporarily nullify built-in or user-defined functions

Assistants in figuring things out

An assistant to understanding:  MapAt or ReplaceAll a Button to prominently display what targets are hit by your operation.
Another assistant:  ParsedForm to show how input parses, before it begins to evaluate
Using HoldForm to what it looked like before evaluation

More on principles and methods

Structural operations are your friends; they work well on unevaluated expressions.

Flatten
Thread
Pointwise operators:  ReplacePart, Delete, FlattenAt, MapAt
Identify what's bad to evaluate:  the whole, or the parts, or the return value?

Some subtle topics to demystify

Functions that hold some or all their arguments, e.g. Plot, Table, and HoldComplete, get all their power of preventing evaluation from attributes.
Misconception:  Block will deactivate absolutely all properties and meaningful behavior of a symbol in Mathematica.  Wrong!  Only rewrite rules are deactivated.
Why is MakeBoxes so nasty, I mean HoldAllComplete?
When to use the different categories of holding stuff?
Myth debunking:  HoldAllComplete isn't some super insulator against the parser, against generic structural operations or pattern-finders or the like.  It is somewhat more powerful than HoldAll, in four ways, and that's it!
Argument evaluation precedes {Listable, Orderless, Flat, ...}, and any other structure-rewriting attributes.
Wrapping an argument in Unevaluated does NOT prevent that argument's head from exercising its UpValues!
"Non-standard Evaluation":  That unexplained complicated thing.
Always anticipate that users might send Unevaluated arguments into your function!
Add a mental red flag to your programming habits

Miscellaneous advanced techniques, and subtle topics

Using tests on patterns:
  /; MyTestQ @ Unevaluated[p]
instead of
  /; MyTestQ[p]
Trott-Strzebonski method for In-Place Evaluation
My Block trick for trapping calls to built-in functions
One-step evaluation using expr /. DownValues[f], and family.
Traps used for tracing should not evaluate what they print or memoize
How to pass arguments to HoldAllComplete functions (such as HoldComplete itself), since Evaluate no longer forces evaluation:  Function @@, With, Block, Replace, ReplacePart
Use strings for symbol names or even to store FullForm of an expression
You can even use Unevaluated as a persistent head, but I don't recommend it for most cases.
Related (another example of a more general issue) issue:  when to wrap incoming argument in Verbatim in case it's a pattern and you're going to pass it to a function that does use pattern semantics when given patterns.

Some examples

I will add quite a few examples from my scratch work in the next revision of this document.

To analyze the code in a package:  read the statements from the file as a list of Hold[stmt]
HoldCompleteForm:  a non-printing variant of HoldComplete (just as HoldForm is to Hold)
Set and SetDelayed can be more flexible.
Temporarily deactivate kernel functions that open files for writing