2.3.5 Putting Constraints on Patterns
Mathematica provides a general mechanism for specifying constraints on patterns. All you need do is to put /; condition at the end of a pattern to signify that it applies only when the specified condition is True. You can read the operator /; as "slashsemi", "whenever" or "provided that".
Putting conditions on patterns and transformation rules.
This gives a definition for fac that applies only when its argument n is positive.
In[1]:= fac[n_ /; n > 0] := n!
The definition for fac is used only when the argument is positive.
In[2]:= fac[6] + fac[4]
Out[2]=
This gives the negative elements in the list.
In[3]:= Cases[{3, 4, 5, 2}, x_ /; x < 0]
Out[3]=
You can use /; on whole definitions and transformation rules, as well as on individual patterns. In general, you can put /; condition at the end of any := definition or :> rule to tell Mathematica that the definition or rule applies only when the specified condition holds. Note that /; conditions should not usually be put at the end of = definitions or > rules, since they will then be evaluated immediately, as discussed in Section 2.5.8.
Here is another way to give a definition which applies only when its argument n is positive.
In[4]:= fac2[n_] := n! /; n > 0
Once again, the factorial functions evaluate only when their arguments are positive.
In[5]:= fac2[6] + fac2[4]
Out[5]=
You can use the /; operator to implement arbitrary mathematical constraints on the applicability of rules. In typical cases, you give patterns which structurally match a wide range of expressions, but then use mathematical constraints to reduce the range of expressions to a much smaller set.
This rule applies only to expressions that have the structure v[x_, 1  x_].
In[6]:= v[x_, 1  x_] := p[x]
This expression has the appropriate structure, so the rule applies.
In[7]:= v[a^2, 1  a^2]
Out[7]=
This expression, while mathematically of the correct form, does not have the appropriate structure, so the rule does not apply.
In[8]:= v[4, 3]
Out[8]=
This rule applies to any expression of the form w[x_, y_], with the added restriction that y == 1  x.
In[9]:= w[x_, y_] := p[x] /; y == 1  x
The new rule does apply to this expression.
In[10]:= w[4, 3]
Out[10]=
In setting up patterns and transformation rules, there is often a choice of where to put /; conditions. For example, you can put a /; condition on the righthand side of a rule in the form lhs :> rhs /; condition, or you can put it on the lefthand side in the form lhs /; condition > rhs. You may also be able to insert the condition inside the expression lhs. The only constraint is that all the names of patterns that you use in a particular condition must appear in the pattern to which the condition is attached. If this is not the case, then some of the names needed to evaluate the condition may not yet have been "bound" in the patternmatching process. If this happens, then Mathematica uses the global values for the corresponding variables, rather than the values determined by pattern matching.
Thus, for example, the condition in f[x_, y_] /; (x + y < 2) will use values for x and y that are found by matching f[x_, y_], but the condition in f[x_ /; x + y < 2, y_] will use the global value for y, rather than the one found by matching the pattern.
As long as you make sure that the appropriate names are defined, it is usually most efficient to put /; conditions on the smallest possible parts of patterns. The reason for this is that Mathematica matches pieces of patterns sequentially, and the sooner it finds a /; condition which fails, the sooner it can reject a match.
Putting the /; condition around the x_ is slightly more efficient than putting it around the whole pattern.
In[11]:= Cases[{z[1, 1], z[1, 1], z[2, 2]}, z[x_ /; x < 0, y_]]
Out[11]=
You need to put parentheses around the /; piece in a case like this.
In[12]:= {1 + a, 2 + a, 3 + a} /. (x_ /; x < 0) + a > p[x]
Out[12]=
It is common to use /; to set up patterns and transformation rules that apply only to expressions with certain properties. There is a collection of functions built into Mathematica for testing the properties of expressions. It is a convention that functions of this kind have names that end with the letter Q, indicating that they "ask a question".
Some functions for testing mathematical properties of expressions.
The rule applies to all elements of the list that are numbers.
In[13]:= {2.3, 4, 7/8, a, b} /. (x_ /; NumberQ[x]) > x^2
Out[13]=
This definition applies only to vectors of integers.
In[14]:= mi[list_] := list^2 /; VectorQ[list, IntegerQ]
The definition is now used only in the first case.
In[15]:= {mi[{2, 3}], mi[{2.1, 2.2}], mi[{a, b}]}
Out[15]=
An important feature of all the Mathematica propertytesting functions whose names end in Q is that they always return False if they cannot determine whether the expression you give has a particular property.
4561 is an integer, so this returns True.
In[16]:= IntegerQ[4561]
Out[16]=
This returns False, since x is not known to be an integer.
In[17]:= IntegerQ[x]
Out[17]=
In some cases, you can explicitly specify the results that propertytesting functions should give. Thus, with a definition such as x /: IntegerQ[x] = True, as discussed in Section 2.5.10, Mathematica will assume that x is an integer. This means that if you explicitly ask for IntegerQ[x], you will now get True, rather than False. However, Mathematica does not automatically propagate assertions, so it cannot determine for example that IntegerQ[x^2] is True. You must load an appropriate Mathematica package to make this possible.
Some functions for testing structural properties of expressions.
With ==, the equation remains in symbolic form; === yields False unless the expressions are manifestly equal.
In[18]:= {x == y, x === y}
Out[18]=
The expression n is not a member of the list {x, x^n}.
In[19]:= MemberQ[{x, x^n}, n]
Out[19]=
However, {x, x^n} is not completely free of n.
In[20]:= FreeQ[{x, x^n}, n]
Out[20]=
You can use FreeQ to define a "linearity" rule for h.
In[21]:= h[a_ b_, x_] := a h[b, x] /; FreeQ[a, x]
Terms free of x are pulled out of each h.
In[22]:= h[a b x, x] + h[2 (1+x) x^2, x]
Out[22]=
Another way to constrain patterns.
The construction pattern /; condition allows you to evaluate a condition involving pattern names to determine whether there is a match. The construction pattern ? test instead applies a function test to the whole expression matched by pattern to determine whether there is a match. Using ? instead of /; sometimes leads to more succinct definitions.
With this definition matches for x_ are tested with the function NumberQ.
In[23]:= p[x_?NumberQ] := x^2
The definition applies only when p has a numerical argument.
In[24]:= p[4.5] + p[3/2] + p[u]
Out[24]=
Here is a more complicated definition. Do not forget the parentheses around the pure function.
In[25]:= q[{x_Integer, y_Integer} ? (Function[v, v.v > 4])] := qp[x + y]
The definition applies only in certain cases.
In[26]:= {q[{3, 4}], q[{1, 1}], q[{5, 7}]}
Out[26]=
