2.6.6 Evaluation in Patterns, Rules and Definitions
There are a number of important interactions in Mathematica between evaluation and pattern matching. The first observation is that pattern matching is usually done on expressions that have already been at least partly evaluated. As a result, it is usually appropriate that the patterns to which these expressions are matched should themselves be evaluated.
The fact that the pattern is evaluated means that it matches the expression given.
In[1]:= f[k^2] /. f[x_^(1 + 1)] > p[x]
Out[1]=
The righthand side of the /; condition is not evaluated until it is used during pattern matching.
In[2]:= f[{a, b}] /. f[list_ /; Length[list] > 1] > list^2
Out[2]=
There are some cases, however, where you may want to keep all or part of a pattern unevaluated. You can do this by wrapping the parts you do not want to evaluate with HoldPattern. In general, whenever HoldPattern[patt] appears within a pattern, this form is taken to be equivalent to patt for the purpose of pattern matching, but the expression patt is maintained unevaluated.
Preventing evaluation in patterns.
One application for HoldPattern is in specifying patterns which can apply to unevaluated expressions, or expressions held in an unevaluated form.
HoldPattern keeps the 1 + 1 from being evaluated, and allows it to match the 1 + 1 on the lefthand side of the /. operator.
In[3]:= Hold[u[1 + 1]] /. HoldPattern[1 + 1] > x
Out[3]=
Notice that while functions like Hold prevent evaluation of expressions, they do not affect the manipulation of parts of those expressions with /. and other operators.
This defines values for r whenever its argument is not an atomic object.
In[4]:= r[x_] := x^2 /; !AtomQ[x]
According to the definition, expressions like r[3] are left unchanged.
In[5]:= r[3]
Out[5]=
However, the pattern r[x_] is transformed according to the definition for r.
In[6]:= r[x_]
Out[6]=
You need to wrap HoldPattern around r[x_] to prevent it from being evaluated.
In[7]:= {r[3], r[5]} /. HoldPattern[r[x_]] > x
Out[7]=
As illustrated above, the lefthand sides of transformation rules such as lhs > rhs are usually evaluated immediately, since the rules are usually applied to expressions which have already been evaluated. The righthand side of lhs > rhs is also evaluated immediately. With the delayed rule lhs :> rhs, however, the expression rhs is not evaluated.
The righthand side is evaluated immediately in > but not :> rules.
In[8]:= {{x > 1 + 1}, {x :> 1 + 1}}
Out[8]=
Here are the results of applying the rules. The righthand side of the :> rule gets inserted inside the Hold without evaluation.
In[9]:= {x^2, Hold[x]} /. %
Out[9]=
Evaluation in transformation rules.
While the lefthand sides of transformation rules are usually evaluated, the lefthand sides of definitions are usually not. The reason for the difference is as follows. Transformation rules are typically applied using /. to expressions that have already been evaluated. Definitions, however, are used during the evaluation of expressions, and are applied to expressions that have not yet been completely evaluated. To work on such expressions, the lefthand sides of definitions must be maintained in a form that is at least partially unevaluated.
Definitions for symbols are the simplest case. As discussed in the previous section, a symbol on the lefthand side of a definition such as x = value is not evaluated. If x had previously been assigned a value y, then if the lefthand side of x = value were evaluated, it would turn into the quite unrelated definition y = value.
Here is a definition. The symbol on the lefthand side is not evaluated.
In[10]:= k = w[3]
Out[10]=
This redefines the symbol.
In[11]:= k = w[4]
Out[11]=
If you evaluate the lefthand side, then you define not the symbol k, but the value w[4] of the symbol k.
In[12]:= Evaluate[k] = w[5]
Out[12]=
Now w[4] has value w[5].
In[13]:= w[4]
Out[13]=
Although individual symbols that appear on the lefthand sides of definitions are not evaluated, more complicated expressions are partially evaluated. In an expression such as f[args] on the lefthand side of a definition, the args are evaluated.
The 1 + 1 is evaluated, so that a value is defined for g[2].
In[14]:= g[1 + 1] = 5
Out[14]=
This shows the value defined for g.
In[15]:= ?g
You can see why the arguments of a function that appears on the lefthand side of a definition must be evaluated by considering how the definition is used during the evaluation of an expression. As discussed in Section 2.6.1, when Mathematica evaluates a function, it first evaluates each of the arguments, then tries to find definitions for the function. As a result, by the time Mathematica applies any definition you have given for a function, the arguments of the function must already have been evaluated. An exception to this occurs when the function in question has attributes which specify that it should hold some of its arguments unevaluated.
Evaluation in definitions.
While in most cases it is appropriate for the arguments of a function that appears on the lefthand side of a definition to be evaluated, there are some situations in which you do not want this to happen. In such cases, you can wrap HoldPattern around the parts that you do not want to be evaluated.
