Given that Mathematica™ is specifically a mathematics computational package, it is tempting for non-computer-programmers to look at an equals sign, =, within Mathematica™ code and expect it to behave as an equals sign in standard math. This notion, unfortunately, can lead the novice Mathematica™ user astray. In Mathematica™, there are several similar symbols that perform different functions, and it is critical to understand those differences.
An infix operator is an operator that is placed between the two items it is operating on. For example, the plus sign, +, is an infix operator because it operates on the combination of the thing before it (called lhs for left-hand-side) and the thing after it (called rhs for right-hand-side). In Mathematica™, and infix operator is usually a shorthand abbreviation for a more standard function. So lhs + rhs is a shorthand for the function Plus[lhs,rhs], which returns the sum of lhs and rhs. In most cases, you do not need to be aware of the underlying functions, although it is occasionally useful to be aware of them.
All of the symbols we will be discussing in this tutorial are infix operators. Here is the list of those operators, along with a brief description of each; more detail will be provided below:
- Set[lhs,rhs], abbreviated lhs = rhs. This function evaluates rhs as fully as possible at the time of execution, and assigns the result to the symbol lhs.
- SetDelayed[lhs,rhs], abbreviated lhs := rhs. This function assigns rhs to the symbol lhs without having first evaluated rhs. rhs is evaluated whenever lhs would be evaluated later in the code.
- Equals[lhs,rhs], abbreviated lhs == rhs (often Mathematica™ will replace the pair of equals signs with a single character ). This function is a logical statement that the expression lhs is equal to the expression rhs. As a logical statement, it can be either True or False. This function does not change any variable assignments.
- Rule[lhs,rhs], abbreviated lhs -> rhs (often Mathematica™ will replace the -> with a single character ). This function represents a transformation of lhs into rhs. rhs is evaluated immediately.
- RuleDelayed[lhs,rhs], abbreviated lhs :> rhs (often Mathematica will replace the :> with a single character ). This function represents a transformation of lhs into rhs, but only evaluating rhs when the transformation rule is applied.
Understanding Set (=) and SetDelayed (:=)
Both Set and SetDelayed assign rhs to the symbol lhs. This means that lhs has to be a setable symbol of some sort. As you can see to the right, a is a symbol that can be set. 1 is not a symbol that can be set (just imagine if we could redefine the definition of the number 1!). And expressions such as a + 1 are not individual symbols
Assigning a value to a symbol is not permanent. In the example to the right we see that b initially is undefined. After assigning the value 1 to b, we get a result of 1 when we use it. But later we can assign a different value to b, overwriting the original value. In this example, b is assigned the result of the calculation 1+1 (i.e., 2).
A symbol, such as c to the right, can be assigned a value that depends on other symbols. In this case, b starts out equal to 2, so c gets assigned the value of 5. Notice that when we change b later, c retains the value of 5 rather than being updated based on the changed value of b, because b+3 was evaluated at the time c was assigned.
SetDelayed (:=), unlike Set, does not evaluate the rhs until the lhs symbol is itself evaluated. Notice to the right, we start with b=0, so when we evaluate d we get 3. But if we change b to be 5, d evaluates to 8. To unassign a symbol, you put a period as the rhs of a Set statement, in which case you can see that d is stored internally as the expression b+3.
So when should you use Set (=) and when should you use SetDelayed (:=)? Often it won’t matter, so it is easy to get in the habit of not paying attention to which you use. This habit can lead to errors, however, so it is worthwhile to occasionally step back from a problem and ask yourself which you are using and why.
SetDelayed has the advantage of flexibility, because you can define a formula and then use that same formula for a variety of different problems. You can use the same formula to calculate an expression numerically and the later do the calculation symbolically, for example to derive a general expression. There are also cases where any value of a parameter is not allowed; for example, perhaps it can only be an integer, and trying to calculate the formula with anything other than an integer is impossible, so you don’t want the calculation to be done only when a particular integer has been chosen. However, SetDelayed has the disadvantage of requiring the evaluation of the rhs to happen each time the lhs symbol is used. Imagine plotting a function, where you need the rhs evaluated at each point along a curve. If that particular calculation is a computationally-intensive one, such as a multi-dimensional integral, SetDelayed would make Mathematica™ do that integral for each data point that gets plotted. If instead you use Set, Mathematica will do the integral once (often symbolically) to get the general answer, and then use that general answer for the specific data points, dramatically speeding up the plot. So both Set and SetDelayed have important uses, and it may take some careful consideration to determine the best one to use in a given context.
Understanding Equals (==)
The operator that acts as a test for equality is Equals (==). As we can see to the right, if the lhs and rhs of Equals evaluate to being equal, Equals returns the value True. If they evaluate to being unequal, Equals returns False. If there is not enough information for the equality to be evaluated, Equals returns the expression itself, evaluated as far as possible.
Equals (==) is the appropriate operator to use when you are asking Mathematica™ to operate on equations as a whole. In the example to the right, we are asking Mathematica™ to solve the ideal gas law for temperature. The curly braces in the result will be described in a future tutorial, and the arrow will be described below.
Set can be used inside expressions, which is simultaneously powerful and a potential source of error. For example, below we have instructed Mathematica™ to solve the expression for the Rydberg constant for Planck’s constant (there are three results because these are three roots to the equation). But if we made a mistake and use a single equals-sign (the Set function) instead of Equals, Mathematica™ gives us an error. Then if we go back and try the Solve command right away, it seems to fail. we can see why if we look at the value of R, which was assigned by the mistaken Set command. Unassigning R lets us return the the behavior we expect.
In practice, this mistake usually doesn’t happen on multiple lines as is shown above. The mistaken use of Set will be executed first, the mistake will be seen and corrected in the original line, and at that point it will be baffling why the Solve doesn’t work. The animation to the right illustrates the typical workflow. And someone coming in to try to help you debug your mistakes, only seeing your correct line, won’t know that you had previously make a mistake that screwed up the definition of R.
Understanding Rule (->) and RuleDelayed (:>)
Rules are used in Mathematica™ for a wide variety of purposes. You saw above that the result of a Solve command comes in the form of rules. Rules are also used to specify options for functions. For example, to the right you can see a Plot call that sets several options using rules to control the way that Plot operates (at this point, don’t worry about the details of how those options work).
But perhaps most-importantly, rules are used to make temporary replacements. This is done in conjunction with the ReplaceAll infix operator, which is abbreviated with /. as shown to the right. You should read “/.” as “where,” and the arrows as “is replaced by.”
A hint of the utility of replacement rules can be seen to the right. Here, we assign the ideal gas law, solved for pressure, to the symbol p. Next, we evaluate p at two different sets of conditions. but the values for R, V, T, and n are only used within their respective single calculations. Finally, we are able to take the first derivative of p with respect to the variable V, and get the result in symbolic form. This would be an unwieldy process if we were to use Set (=) to assign R, V, T, and n each time, and then unset them using =. before doing the symbolic derivative.
In quantum mechanics, it is quite common to use multiple unit systems. Sometimes we want to manipulate a wavefunction entirely symbolically. Sometimes we want to solve an equation involving a wavefunction in SI units. Sometimes we want to solve an equation involving a wavefunction in atomic units. If we assign replacement rules for the fundamental physical constants in different unit systems to symbols called something like SIUnits or AtomicUnits, then we can perform a calculation in those unit systems by simply adding a ReplaceAll after the expression to be evaluated, such as: ComplexExpression/.AtomicUnits. We will use replacement rules in this and many other contexts throughout these tutorials and other materials.
RuleDelayed (:>) is exactly like Rule, but where the rhs is not evaluated until the rule is used. The cases where this is necessary are much fewer than those where SetDelayed is necessary, so I won’t be going into examples of its use here.