Introduction to Mathematical Software

21-126, Spring 2000
Dr. David Handron

Lesson 3

Introducing Evaluation in Mathematica

Introduction

In the previous section we introduced Mathematica expressions. A typical expression is

f = x^2 + b x + 7

The FullForm[]  of an expression f = g is Set[f,g], i.e. the equals sign (=) is just a short cut for the Set[] command. However, it is difficult to observe this, since when an expression like the above is evaluated it always prints out the right hand side. The Hold[] command will "freeze" an expression so that it is not evaluated (or executed). This allows us to use FullForm[] to see what's going on.

Hold[ f  =  g]FullForm[ % ]

Setting f to be the quadratic expression x^2 + b x + 7 causes Mathematica to replace all occurrences of f in subsequent expressions by x^2 + b x + 7. For example:

f = x^2 + b x + 7
g = x^3 + f

This is an example of how Mathematica "evaluates" expressions. As you may recall, the command ?f will remind you what value the name f is Set to:

?f

These assignments (really Set[]'s) are Evaluation Rules and play an important role in how Mathematica functions. 
 
To remove evaluation rules, use the ClearAll[] command

g

ClearAll[g] 
?g

Finally, we observe that Mathematica uses "full recursive evaluation", meaning that it applies all of its rules to an expression over and over until nothing changes. To see this at work consider the following

g = x^3 + f

At this point it is natural to ask: What happens to g if we change f to f = y; does g change to x^3 + y or does it remain the same or do we get an error ? 
 
Take a guess before entering the next command!

f = y 
g

Clearly g didn't change.  
 
To understand why not, we recall that Mathematica uses full recursive evaluation, so that the sequence of events that went on when we evaluated the expression g = x^3 + f (by hitting the shift return keys) was 
 
Set[g, x^3 + f]  --->  Set[g, x^3 + x^2 + b*x + 7]  
 
and then the Set[] function was evaluated. 
 
Understanding this, you should be able to predict the outputs from the following:

ClearAll[f,g] 
g = x^3 + f

f = x^2 + b x + 7 
g

f = y 
g

Evaluation, Rule[]'s and Mathematical Functions

In the previous section we considered a quadratic expression f = x^2 + b x + 7. Frequently we want to think of this as a mathematical function with independent variable x, and may want to evaluate f for various values of x. Let's Set[] f to be this expression

ClearAll[f,g,x,y]
f = x^2 + b x + 7

To find the value of this expression when x = 3 we can Set[] x to be 3 and ask Mathematica to evaluate f

x = 3 
f

This is another example of recursive evaluation, f evaluated to an expression involving x's, but then the x's were fully evaluated to 3's.  
 
To get f back to its generic form we must Clear[] x.

Clear[x] 
f

The whole process of setting x, evaluating f and then clearing x just to find "f(3)" is rather tedious, and can be circumvented using the ReplaceAll[] command. This command takes a name, like f, and a Rule[] such as Rule[x,3], which is interpreted by the RelpaceAll[] command to replace all x's by 3's.

ReplaceAll[f, Rule[x,3]] 
f

Note that f didn't change. 
 
Since this construction is often used, the front end provides abbreviations for the ReplaceAll[] and Rule[] commands. The rule Rule[x,3] is abbreviated by x -> 3 (the arrow is constructed using the minus and greater than key) and the ReplaceAll[] command is abbreviated by /. (slash dot).

f /. x -> 3

To apply many rules at once, ReplaceAll[] will accept a List[] of Rule[]'s for its second argument.

f = x^2 + y^2 
f /. {x->3,y->4}

Patterns and Evaluation Rules

Basic Patterns

The generic symbol to match any single expression is the underscore.

MatchQ[x^2+5, _]

MatchQ[blue,_]

MatchQ[f[x], _]

As you can guess from the above, MatchQ[] returns true or false depending upon whether or not the first argument matches the second. If you want to refer to an expression with a particular head, such as an integer, you may put the head after the underscore.

MatchQ[2, _Integer]

MatchQ[x^2+5, _Integer]

MatchQ[f[x,y,z], _f]

It is also possible to match compound expressions. For example, suppose we want to build a pattern that will match f[x,y], where x and y may be arbitrary expressions. The pattern for this would be f[_,_]

MatchQ[f[x,y^+1], f[_,_]]

MatchQ[f[x,y,z], f[_,_]]

Notice that to get these expressions to match, f[] had to have exactly two arguments. If we want to make a pattern that matches f[] with any number of arguments we may use a double underscore.

MatchQ[f[x,y^2+1], f[__]]

MatchQ[f[x,y,z], f[__]]

MatchQ[f[], f[__]]

As shown by this last example, the double underscore will not match the empty set. To match any number of expressions, including none, use a triple underscore.

MatchQ[f[], f[___]]

MatchQ[f[x,y,z], f[___]]

Patterns and Evaluation Rules

Recall the follow simple example we used when discussion evaluation:

f = x^2 + x + 7

Recall that the kernel stored the information about f as shown with ?

?f

Patterns can be used to construct more complicated evaluation rules. Suppose that we wanted f to represent the constant function 1.

Clear[f] 
f[_] = 1

Now the kernel will replace an expression like f[x] with one, but not expressions like f[x,y] (we would need to use a pattern like f[_,_] or f[__] to match f[x,y]).

f[7] 
f[z]

f[x,y]

?f

It is possible to associate many patterns with the symbol f. Suppose, for example, we wanted f[x,y] to evaluate to 1 if x or y is of type integer, but to remain unevaluated otherwise. The following assignment would accomplish this.

Clear[f] 
f[_Integer, _] = 1 
f[_, _Integer] = 1 
?f

A few examples will illustrate the operation of these evaluation rules.

f[x,y] 
f[x,17] 
f[19,x] 
f[12,3]

A Common Mistake

When making up multiple evaluation rules, such as those for f[] above, I strongly suggest that you put all of the rules in a single input cell which begins with a Clear[] statement. It is also a good idea to end the input cell with a ? to check to see that Mathematica digested all of the rules the way you thought it would. 
 
To illustrate what can go wrong, suppose we wanted to make an evaluation rule that evaluated f[x] to be 1 whenever x an integer, and to remain unevaluated otherwise. A good programmer always clears the variables:

Clear[f]

Next we write the evaluation rule

f[_] = 1

Oh gosh! This isn't quite correct, I meant to type _Integer instead of the plain underscore. Not to worry, with one click of the mouse I can fix it. (At this point you would typically use the mouse to change the bad statement above to the one I'll type in below.)

f[_Integer] = 1

Remember, the bad statement would no longer be on the screen; however, out of sight doesn't mean out of mind (kernel?)

f[1]

f[x]

Can you see what went wrong?

?f

Both rules survived, since we never cleared f after typing in the bad rule. The correct way of coding this to avoid spurious rules is

Clear[f] 
f[_Integer] = 1 
?f

f[1] 
f[x]

Even if you make a mistake, putting the Clear[] statement in the same cell makes sure f is cleared every time the cell is executed. Putting ?f at the end of the cell provides prints out all of the evaluation rules known for f for you to see.

Summary

_ 	Match any expression 
__	Match one or more expressions 
___	Match any number of expressions 
 
_h	Match an expression with head h 
x_	Name the pattern x 
 
:= 	Delay evaluation of right hand side (full form is SetDelayed[]) 
/;	Condition[], evaluate only when is True 
 
In general, all rules should be put into a single input cell that begins with Clear[] and (at least while debugging your code) end with ?