2.6.5 NonStandard Evaluation
While most builtin Mathematica functions follow the standard evaluation procedure, some important ones do not. For example, most of the Mathematica functions associated with the construction and execution of programs use nonstandard evaluation procedures. In typical cases, the functions either never evaluate some of their arguments, or do so in a special way under their own control.
Some functions that use nonstandard evaluation procedures.
When you give a definition such as a = 1, Mathematica does not evaluate the a that appears on the lefthand side. You can see that there would be trouble if the a was evaluated. The reason is that if you had previously set a = 7, then evaluating a in the definition a = 1 would put the definition into the nonsensical form 7 = 1.
In the standard evaluation procedure, each argument of a function is evaluated in turn. This is prevented by setting the attributes HoldFirst, HoldRest and HoldAll. These attributes make Mathematica "hold" particular arguments in an unevaluated form.
Attributes for holding function arguments in unevaluated form.
With the standard evaluation procedure, all arguments to a function are evaluated.
In[1]:= f[1 + 1, 2 + 4]
Out[1]=
This assigns the attribute HoldFirst to h.
In[2]:= SetAttributes[h, HoldFirst]
The first argument to h is now held in an unevaluated form.
In[3]:= h[1 + 1, 2 + 4]
Out[3]=
When you use the first argument to h like this, it will get evaluated.
In[4]:= h[1 + 1, 2 + 4] /. h[x_, y_] > x^y
Out[4]=
Builtin functions like Set carry attributes such as HoldFirst.
In[5]:= Attributes[Set]
Out[5]=
Even though a function may have attributes which specify that it should hold certain arguments unevaluated, you can always explicitly tell Mathematica to evaluate those arguments by giving the arguments in the form Evaluate[arg].
Evaluate effectively overrides the HoldFirst attribute, and causes the first argument to be evaluated.
In[6]:= h[Evaluate[1 + 1], 2 + 4]
Out[6]=
Forcing the evaluation of function arguments.
By holding its arguments, a function can control when those arguments are evaluated. By using Evaluate, you can force the arguments to be evaluated immediately, rather than being evaluated under the control of the function. This capability is useful in a number of circumstances.
One example discussed in Section 1.9.1 occurs when plotting graphs of expressions. The Mathematica Plot function holds unevaluated the expression you are going to plot, then evaluates it at a sequence of numerical positions. In some cases, you may instead want to evaluate the expression immediately, and have Plot work with the evaluated form. For example, if you want to plot a list of functions generated by Table, then you will want the Table operation done immediately, rather than being done every time a point is to be plotted.
Evaluate causes the list of functions to be constructed immediately, rather than being constructed at each value of x chosen by Plot.
In[7]:= Plot[ Evaluate[Table[Sin[n x], {n, 1, 3}]], {x, 0, 2Pi} ]
Out[7]=
There are a number of builtin Mathematica functions which, like Plot, are set up to hold some of their arguments. You can always override this behavior using Evaluate.
The Mathematica Set function holds its first argument, so the symbol a is not evaluated in this case.
In[8]:= a = b
Out[8]=
You can make Set evaluate its first argument using Evaluate. In this case, the result is the object which is the value of a, namely b is set to 6.
In[9]:= Evaluate[a] = 6
Out[9]=
b has now been set to 6.
In[10]:= b
Out[10]=
In most cases, you want all expressions you give to Mathematica to be evaluated. Sometimes, however, you may want to prevent the evaluation of certain expressions. For example, if you want to manipulate pieces of a Mathematica program symbolically, then you must prevent those pieces from being evaluated while you are manipulating them.
You can use the functions Hold and HoldForm to keep expressions unevaluated. These functions work simply by carrying the attribute HoldAll, which prevents their arguments from being evaluated. The functions provide "wrappers" inside which expressions remain unevaluated.
The difference between Hold[expr] and HoldForm[expr] is that in standard Mathematica output format, Hold is printed explicitly, while HoldForm is not. If you look at the full internal Mathematica form, you can however see both functions.
Hold maintains expressions in an unevaluated form.
In[11]:= Hold[1 + 1]
Out[11]=
HoldForm also keeps expressions unevaluated, but is invisible in standard Mathematica output format.
In[12]:= HoldForm[1 + 1]
Out[12]=
HoldForm is still present internally.
In[13]:= FullForm[%]
Out[13]//FullForm=
The function ReleaseHold removes Hold and HoldForm, so the expressions they contain get evaluated.
In[14]:= ReleaseHold[%]
Out[14]=
Functions for handling unevaluated expressions.
Parts of expressions are usually evaluated as soon as you extract them.
In[15]:= Extract[ Hold[1 + 1, 2 + 3], 2]
Out[15]=
This extracts a part and immediately wraps it with Hold, so it does not get evaluated.
In[16]:= Extract[ Hold[1 + 1, 2 + 3], 2, Hold]
Out[16]=
The last argument of 1 tells ReplacePart to extract the first part of Hold[7 + 8] before inserting it.
In[17]:= ReplacePart[ Hold[1 + 1, 2 + 3], Hold[7 + 8], 2, 1]
Out[17]=
Temporary prevention of argument evaluation.
1 + 1 evaluates to 2, and Length[2] gives 0.
In[18]:= Length[1 + 1]
Out[18]=
This gives the unevaluated form 1 + 1 as the argument of Length.
In[19]:= Length[Unevaluated[1 + 1]]
Out[19]=
Unevaluated[expr] effectively works by temporarily giving a function an attribute like HoldFirst, and then supplying expr as an argument to the function.
Attributes for preventing other aspects of evaluation.
By setting the attribute HoldAll, you can prevent Mathematica from evaluating the arguments of a function. But even with this attribute set, Mathematica will still do some transformations on the arguments. By setting SequenceHold you can prevent it from flattening out Sequence objects that appear in the arguments. And by setting HoldAllComplete you can also inhibit the stripping of Unevaluated, and prevent Mathematica from using any upvalues it finds associated with the arguments.
