Non-Standard Evaluation

While most built-in Wolfram Language functions follow the standard evaluation procedure, some important ones do not. For example, most of the Wolfram Language functions associated with the construction and execution of programs use non-standard 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 non-standard evaluation procedures.

When you give a definition such as a=1, the Wolfram Language does not evaluate the a that appears on the left-hand 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 (RefLink[HoldFirst, paclet:ref/HoldFirst]), (RefLink[HoldRest, paclet:ref/HoldRest]) and (RefLink[HoldAll, paclet:ref/HoldAll]). These attributes make the Wolfram Language "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:

f[1+1,2+4]

This assigns the attribute (RefLink[HoldFirst, paclet:ref/HoldFirst]) to h:

SetAttributes[h,HoldFirst]

The first argument to h is now held in an unevaluated form:

h[1+1,2+4]

When you use the first argument to h like this, it will get evaluated:

h[1+1,2+4]/.h[x_,y_]->x^y

Built-in functions like (RefLink[Set, paclet:ref/Set]) carry attributes such as (RefLink[HoldFirst, paclet:ref/HoldFirst]):

Attributes[Set]

Even though a function may have attributes which specify that it should hold certain arguments unevaluated, you can always explicitly tell the Wolfram Language to evaluate those arguments by giving the arguments in the form (RefLink[Evaluate, paclet:ref/Evaluate])[arg].

(RefLink[Evaluate, paclet:ref/Evaluate]) effectively overrides the (RefLink[HoldFirst, paclet:ref/HoldFirst]) attribute, and causes the first argument to be evaluated:

h[Evaluate[1+1],2+4]

Forcing the evaluation of function arguments.

By holding its arguments, a function can control when those arguments are evaluated. By using (RefLink[Evaluate, paclet:ref/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.

The Wolfram Language (RefLink[Set, paclet:ref/Set]) function holds its first argument, so the symbol a is not evaluated in this case:

a=b

You can make (RefLink[Set, paclet:ref/Set]) evaluate its first argument using (RefLink[Evaluate, paclet:ref/Evaluate]). In this case, the result is the object which is the value of a, namely b is set to 6:

Evaluate[a]=6

b has now been set to 6:

b

In most cases, you want all expressions you give to the Wolfram Language 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 Wolfram Language program symbolically, then you must prevent those pieces from being evaluated while you are manipulating them.

You can use the functions (RefLink[Hold, paclet:ref/Hold]) and (RefLink[HoldForm, paclet:ref/HoldForm]) to keep expressions unevaluated. These functions work simply by carrying the attribute (RefLink[HoldAll, paclet:ref/HoldAll]), which prevents their arguments from being evaluated. The functions provide "wrappers" inside which expressions remain unevaluated.

The difference between (RefLink[Hold, paclet:ref/Hold])[expr] and (RefLink[HoldForm, paclet:ref/HoldForm])[expr] is that in standard Wolfram Language output format, (RefLink[Hold, paclet:ref/Hold]) is printed explicitly, while (RefLink[HoldForm, paclet:ref/HoldForm]) is not. If you look at the full internal Wolfram Language form, you can however see both functions.

(RefLink[Hold, paclet:ref/Hold]) maintains expressions in an unevaluated form:

Hold[1+1]

(RefLink[HoldForm, paclet:ref/HoldForm]) also keeps expressions unevaluated, but is invisible in standard Wolfram Language output format:

HoldForm[1+1]

(RefLink[HoldForm, paclet:ref/HoldForm]) is still present internally:

FullForm[%]

The function (RefLink[ReleaseHold, paclet:ref/ReleaseHold]) removes (RefLink[Hold, paclet:ref/Hold]) and (RefLink[HoldForm, paclet:ref/HoldForm]), so the expressions they contain get evaluated:

ReleaseHold[%]

Functions for handling unevaluated expressions.

Parts of expressions are usually evaluated as soon as you extract them:

Extract[Hold[1+1,2+3],2]

This extracts a part and immediately wraps it with (RefLink[Hold, paclet:ref/Hold]), so it does not get evaluated:

Extract[Hold[1+1,2+3],2,Hold]

Temporary prevention of argument evaluation.

1+1 evaluates to 2, and (RefLink[Length, paclet:ref/Length])[2] gives 0:

Length[1+1]

This gives the unevaluated form 1+1 as the argument of (RefLink[Length, paclet:ref/Length]):

Length[Unevaluated[1+1]]

(RefLink[Unevaluated, paclet:ref/Unevaluated])[expr] effectively works by temporarily giving a function an attribute like (RefLink[HoldFirst, paclet:ref/HoldFirst]), and then supplying expr as an argument to the function.

Attributes for preventing other aspects of evaluation.

By setting the attribute (RefLink[HoldAll, paclet:ref/HoldAll]), you can prevent the Wolfram Language from evaluating the arguments of a function. But even with this attribute set, the Wolfram Language will still do some transformations on the arguments. By setting (RefLink[SequenceHold, paclet:ref/SequenceHold]) you can prevent it from flattening out (RefLink[Sequence, paclet:ref/Sequence]) objects that appear in the arguments. And by setting (RefLink[HoldAllComplete, paclet:ref/HoldAllComplete]) you can also inhibit the stripping of (RefLink[Unevaluated, paclet:ref/Unevaluated]), and prevent the Wolfram Language from using any upvalues it finds associated with the arguments.