Evaluation of Expressions
Evaluation of Expressions
The fundamental operation that the Wolfram Language performs isevaluation. Whenever you enter an expression, the Wolfram Language evaluates the expression, then returns the result.
Evaluation in the Wolfram Language works by applying a sequence of definitions. The definitions can either be ones you explicitly entered, or ones that are built into the Wolfram Language.
Thus, for example, the Wolfram Language evaluates the expression6+7 using a built‐in procedure for adding integers. Similarly, the Wolfram Language evaluates the algebraic expressionx-3x+1 using a built‐in simplification procedure. If you had made the definitionx=5, then the Wolfram Language would use this definition to reducex-3x+1 to-9.
The two most central concepts in the Wolfram Language are probablyexpressions andevaluation."Expressions" discusses how all the different kinds of objects that the Wolfram Language handles are represented in a uniform way using expressions. This tutorial describes how all the operations that the Wolfram Language can perform can also be viewed in a uniform way as examples of evaluation.
The Wolfram Language is aninfinite evaluation system. When you enter an expression, the Wolfram Language will keep on using definitions it knows until it gets a result to which no definitions apply.
If you ask forfac[10], the Wolfram Language will keep on applying the definitions you have given until the result it gets no longer changes:
When the Wolfram Language has used all the definitions it knows, it gives whatever expression it has obtained as the result. Sometimes the result may be an object such as a number. But usually the result is an expression in which some objects are represented in a symbolic form.
The Wolfram Language uses its built‐in definitions for simplifying sums, but knows no definitions forf[3], so leaves this in symbolic form:
The Wolfram Language follows the principle of applying definitions until the result it gets no longer changes. This means that if you take the final result that the Wolfram Language gives, and enter it as Wolfram Language input, you will get back the same result again. (There are some subtle cases discussed in"Controlling Infinite Evaluation" in which this does not occur.)
At any given time, the Wolfram Language can only use those definitions that it knows at that time. If you add more definitions later, however, the Wolfram Language will be able to use these. The results you get from the Wolfram Language may change in this case.
The simplest examples of evaluation involve using definitions such asf[x_]=x^2 which transform one expression directly into another. But evaluation is also the process used to execute programs written in the Wolfram Language. Thus, for example, if you have a procedure consisting of a sequence of Wolfram Language expressions, some perhaps representing conditionals and loops, the execution of this procedure corresponds to the evaluation of these expressions. Sometimes the evaluation process may involve evaluating a particular expression several times, as in a loop.
The built‐in functions in the Wolfram Language operate in a wide variety of ways. But many of the mathematical functions share an important approach: they are set up so as to reduce classes of mathematical expressions to standard forms.
The built‐in definitions for thePlus function, for example, are set up to write any sum of terms in a standard unparenthesized form. The associativity of addition means that expressions like(a+b)+c,a+(b+c) anda+b+c are all equivalent. But for many purposes it is convenient for all these forms to be reduced to the single standard forma+b+c. The built‐in definitions forPlus are set up to do this.
Through the built‐in definitions forPlus, this expression is reduced to a standard unparenthesized form:
Whenever the Wolfram Language knows that a function is associative, it tries to remove parentheses (or nested invocations of the function) to get the function into a standard "flattened" form.
A function like addition is not only associative, but also commutative, which means that expressions likea+c+b anda+b+c with terms in different orders are equal. Once again, the Wolfram Language tries to put all such expressions into a "standard" form. The standard form it chooses is the one in which all the terms are in a definite order, corresponding roughly to alphabetical order.
Two important properties that the Wolfram Language uses in reducing certain functions to standard form.
There are several reasons to try to put expressions into standard forms. The most important is that if two expressions are really in standard form, it is obvious whether or not they are equal.
When the two sums are put into standard order, they are immediately seen to be equal, so that twof's cancel, leaving the result0:
You could imagine finding out whethera+c+b was equal toc+a+b by testing all possible orderings of each sum. It is clear that simply reducing both sums to standard form is a much more efficient procedure.
One might think that the Wolfram Language should somehow automatically reduceall mathematical expressions to a single standard canonical form. With all but the simplest kinds of expressions, however, it is quite easy to see that you do not want thesame standard form for all purposes.
For polynomials, for example, there are two obvious standard forms, which are good for different purposes. The first standard form for a polynomial is a simple sum of terms, as would be generated in the Wolfram Language by applying the functionExpand. This standard form is most appropriate if you need to add and subtract polynomials.
There is, however, another possible standard form that you can use for polynomials. By applyingFactor, you can write any polynomial as a product of irreducible factors. This canonical form is useful if you want to do operations like division.
Expanded and factored forms are in a sense both equally good standard forms for polynomials. Which one you decide to use simply depends on what you want to use it for. As a result, the Wolfram Language does not automatically put polynomials into one of these two forms. Instead, it gives you functions likeExpand andFactor that allow you explicitly to put polynomials in whatever form you want.
You can write both of them in expanded form just by applyingExpand. In this form, the equality of the polynomials is obvious:
Although it is clear that you do not always want expressions reduced to thesame standard form, you may wonder whether it is at leastpossible to reduce all expressions tosome standard form.
There is a basic result in the mathematical theory of computation which shows that this is, in fact, not always possible. You cannot guarantee that any finite sequence of transformations will take any two arbitrarily chosen expressions to a standard form.
In a sense, this is not particularly surprising. If you could in fact reduce all mathematical expressions to a standard form, then it would be quite easy to tell whether any two expressions were equal. The fact that so many of the difficult problems of mathematics can be stated as questions about the equality of expressions suggests that this can in fact be difficult.
Definitions such asf[x_]=x^2 specifyvalues for functions. Sometimes, however, you need to specify general properties of functions, without necessarily giving explicit values.
The Wolfram Language provides a selection ofattributes that you can use to specify various properties of functions. For example, you can use the attributeFlat to specify that a particular function is "flat", so that nested invocations are automatically flattened, and it behaves as if it were associative.
Nowf behaves as a flat, or associative, function, so that nested invocations are automatically flattened:
Attributes likeFlat can affect not only evaluation, but also operations such as pattern matching. If you give definitions or transformation rules for a function, you must be sure to have specified the attributes of the function first.
| Attributes[f] | give the attributes off |
| Attributes[f]={attr1,attr2,…} | set the attributes off |
| Attributes[f]={} | setf to have no attributes |
| SetAttributes[f,attr] | addattr to the attributes off |
| ClearAttributes[f,attr] | removeattr from the attributes off |
| Orderless | orderless, commutative function(arguments are sorted into standard order) |
| Flat | flat, associative function(arguments are "flattened out") |
| OneIdentity | f[f[a]], etc. are equivalent toa for pattern matching |
| Listable | f is automatically "threaded" over lists that appear as arguments(e.g.,f[{a,b}] becomes{f[a],f[b]}) |
| Constant | all derivatives off are zero |
| NumericFunction | f is assumed to have a numerical value when its arguments are numeric quantities |
| Protected | values off cannot be changed |
| Locked | attributes off cannot be changed |
| ReadProtected | values off cannot be read |
| HoldFirst | the first argument off is not evaluated |
| HoldRest | all but the first argument off are not evaluated |
| HoldAll | none of the arguments off are evaluated |
| HoldAllComplete | the arguments off are treated as completely inert |
| NHoldFirst | the first argument off is not affected byN |
| NHoldRest | all but the first argument off are not affected byN |
| NHoldAll | none of the arguments off are affected byN |
| SequenceHold | Sequence objects appearing in the arguments off are not flattened out |
| Temporary | f is a local variable, removed when no longer used |
| Stub | Needs is automatically called iff is ever explicitly input |
An important attribute assigned to built‐in mathematical functions in the Wolfram Language is the attributeListable. This attribute specifies that a function should automatically be distributed or "threaded" over lists that appear as its arguments. This means that the function effectively gets applied separately to each element in any lists that appear as its arguments.
Many of the attributes you can assign to functions in the Wolfram Language directly affect the evaluation of those functions. Some attributes, however, affect only other aspects of the treatment of functions. For example, the attributeOneIdentity affects only pattern matching, as discussed in"Flat and Orderless Functions". Similarly, the attributeConstant is only relevant in differentiation, and operations that rely on differentiation.
TheProtected attribute affects assignments. The Wolfram Language does not allow you to make any definition associated with a symbol that carries this attribute. The functionsProtect andUnprotect discussed in"Modifying Built-in Functions" can be used as alternatives toSetAttributes andClearAttributes to set and clear this attribute. As discussed in"Modifying Built-in Functions", most built‐in Wolfram Language objects are initially protected so that you do not make definitions for them by mistake.

You can usually see the definitions you have made for a particular symbol by typing?f, or by using a variety of built‐in Wolfram Language functions. However, if you set the attributeReadProtected, the Wolfram Language will not allow you to look at the definition of a particular symbol. It will nevertheless continue to use the definitions in performing evaluation.
Functions likeSetAttributes andClearAttributes usually allow you to modify the attributes of a symbol in any way. However, if you once set theLocked attribute on a symbol, then the Wolfram Language will not allow you to modify the attributes of that symbol for the remainder of your Wolfram System session. Using theLocked attribute in addition toProtected orReadProtected, you can arrange for it to be impossible for users to modify or read definitions.
By defining attributes for a function you specify properties that the Wolfram Language should assume whenever that function appears. Often, however, you want to assume the properties only in a particular instance. In such cases, you will be better off not to use attributes, but instead to call a particular function to implement the transformation associated with the attributes.
By explicitly callingThread, you can implement the transformation that would be done automatically ifp were listable:
Attributes in the Wolfram Language can only be permanently defined for single symbols. However, the Wolfram Language also allows you to set up pure functions which behave as if they carry attributes.
| Function[vars,body,{attr1,…}] | a pure function with attributesattr1,… |
By adding the attributeListable, the function gets distributed over the elements of the list before applyingp:
Here the standard procedure used by the Wolfram System to evaluate expressions is described. This procedure is the one followed for most kinds of expression. There are, however, some kinds of expressions, such as those used to represent the Wolfram System programs and control structures, that are evaluated in a nonstandard way.
In the standard evaluation procedure, the Wolfram System first evaluates the head of an expression and then evaluates each element of the expression. These elements are in general themselves expressions, to which the same evaluation procedure is recursively applied.
The threePrint functions are evaluated in turn, each printing its argument, then returning the valueNull:
As soon as the Wolfram System has evaluated the head of an expression, it sees whether the head is a symbol that has attributes. If the symbol has the attributesOrderless,Flat, orListable, then immediately after evaluating the elements of the expression the Wolfram System performs the transformations associated with these attributes.
The next step in the standard evaluation procedure is to use definitions that the Wolfram System knows for the expression it is evaluating. The Wolfram System first tries to use definitions that you have made, and if there are none that apply, it tries built‐in definitions.
If the Wolfram System finds a definition that applies, it performs the corresponding transformation on the expression. The result is another expression, which must then in turn be evaluated according to the standard evaluation procedure.
■ Evaluate the head of the expression. |
■ Evaluate each element in turn. |
■ Apply any definitions that you have given. |
■ Apply any built‐in definitions. |
■ Evaluate the result. |
As discussed in"Principles of Evaluation", the Wolfram System follows the principle that each expression is evaluated until no further definitions apply. This means that the Wolfram System must continue reevaluating results until it gets an expression that remains unchanged through the evaluation procedure.
Here is an example that shows how the standard evaluation procedure works on a simple expression. Assume thata=7.
| 2ax+a^2+1 | here is the original expression |
| Plus[Times[2,a,x],Power[a,2],1] | this is the internal form |
| Times[2,a,x] | this is evaluated first |
| Times[2,7,x] | a is evaluated to give 7 |
| Times[14,x] | built‐in definitions forTimes give this result |
| Power[a,2] | this is evaluated next |
| Power[7,2] | here is the result after evaluatinga |
| 49 | built‐in definitions forPower give this result |
| Plus[Times[14,x],49,1] | here is the result after the arguments ofPlus have been evaluated |
| Plus[50,Times[14,x]] | built‐in definitions forPlus give this result |
| 50+14x | the result is printed like this |
The Wolfram System provides various ways to "trace" the evaluation process, as discussed in"Tracing Evaluation". The functionTrace[expr] gives a nested list showing each subexpression generated during evaluation. (Note that the standard evaluation traverses the expression tree in a depth‐first way, so that the smallest subparts of the expression appear first in the results ofTrace.)
This gives a nested list of all the subexpressions generated during the evaluation of the expression:
The order in which the Wolfram System applies different kinds of definitions is important. The fact that the Wolfram System applies definitions you have given before it applies built‐in definitions means that you can give definitions that override the built‐in ones, as discussed in"Modifying Built-in Functions".
You can give your own definitions forArcSin. You need to remove the protection attribute first:
As discussed in"Associating Definitions with Different Symbols", you can associate definitions with symbols either as upvalues or downvalues. The Wolfram System always tries upvalue definitions before downvalue ones.
If you have an expression likef[g[x]], there are, in general, two sets of definitions that could apply: downvalues associated withf and upvalues associated withg. The Wolfram System tries the definitions associated withg before those associated withf.
This ordering follows the general strategy of trying specific definitions before more general ones. By applying upvalues associated with arguments before applying downvalues associated with a function, the Wolfram System allows you to make definitions for special arguments that override the general definitions for the function with any arguments.
■ Definitions associated withg are applied before definitions associated withf in the expressionf[g[x]]. |
Most functions such asPlus that are built into the Wolfram System have downvalues. There are, however, some objects in the Wolfram System that have built‐in upvalues. For example,SeriesData objects, which represent power series, have built‐in upvalues with respect to various mathematical operations.
For an expression likef[g[x]], the complete sequence of definitions that are tried in the standard evaluation procedure is:
- Definitions you have given associated withg;
- Built‐in definitions associated withg;
- Definitions you have given associated withf;
- Built‐in definitions associated withf.
The fact that upvalues are used before downvalues is important in many situations. In a typical case, you might want to define an operation such as composition. If you give upvalues for various objects with respect to composition, these upvalues will be used whenever such objects appear. However, you can also give a general procedure for composition, to be used if no special objects are present. You can give this procedure as a downvalue for composition. Since downvalues are tried after upvalues, the general procedure will be used only if no objects with upvalues are present.
In general, there can be several objects that have upvalues in a particular expression. The Wolfram System first looks at the head of the expression and tries any upvalues associated with it. Then it successively looks at each element of the expression, trying any upvalues that exist. The Wolfram System performs this procedure first for upvalues that you have explicitly defined, and then for upvalues that are built-in. The procedure means that in a sequence of elements, upvalues associated with earlier elements take precedence over those associated with later elements.
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.
| x=y | do not evaluate the left‐hand side |
| If[p,a,b] | |
| Do[expr,{n}] | evaluateexprn times |
| Plot[f,{x,…}] | evaluatef with a sequence of numerical values forx |
| Function[{x},body] | do not evaluate until the function is applied |
When you give a definition such asa=1, the Wolfram Language does not evaluate thea that appears on the left‐hand side. You can see that there would be trouble if thea was evaluated. The reason is that if you had previously seta=7, then evaluatinga in the definitiona=1 would put the definition into the nonsensical form7=1.
In the standard evaluation procedure, each argument of a function is evaluated in turn. This is prevented by setting the attributesHoldFirst,HoldRest andHoldAll. These attributes make the Wolfram Language "hold" particular arguments in an unevaluated form.
| HoldFirst | do not evaluate the first argument |
| HoldRest | evaluate only the first argument |
| HoldAll | evaluate none of the arguments |
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 formEvaluate[arg].
Evaluate effectively overrides theHoldFirst attribute, and causes the first argument to be evaluated:
| f[Evaluate[arg]] | evaluatearg immediately, even though attributes off may specify that it should be held |
By holding its arguments, a function can control when those arguments are evaluated. By usingEvaluate, 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 LanguageSet function holds its first argument, so the symbola is not evaluated in this case:
You can makeSet evaluate its first argument usingEvaluate. In this case, the result is the object which is thevalue ofa, namelyb is set to6:
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 functionsHold andHoldForm to keep expressions unevaluated. These functions work simply by carrying the attributeHoldAll, which prevents their arguments from being evaluated. The functions provide "wrappers" inside which expressions remain unevaluated.
The difference betweenHold[expr] andHoldForm[expr] is that in standard Wolfram Language output format,Hold is printed explicitly, whileHoldForm is not. If you look at the full internal Wolfram Language form, you can however see both functions.
Hold maintains expressions in an unevaluated form:
HoldForm also keeps expressions unevaluated, but is invisible in standard Wolfram Language output format:
HoldForm is still present internally:
| Hold[expr] | keepexpr unevaluated |
| HoldComplete[expr] | keepexpr unevaluated and prevent upvalues associated withexpr from being used |
| HoldForm[expr] | |
| ReleaseHold[expr] | |
| Extract[expr,index,Hold] |
This extracts a part and immediately wraps it withHold, so it does not get evaluated:
| f[…,Unevaluated[expr],…] | giveexpr unevaluated as an argument tof |
Unevaluated[expr] effectively works by temporarily giving a function an attribute likeHoldFirst, and then supplyingexpr as an argument to the function.
| SequenceHold | do not flatten outSequence objects that appear as arguments |
| HoldAllComplete | treat all arguments as completely inert |
By setting the attributeHoldAll, 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 settingSequenceHold you can prevent it from flattening outSequence objects that appear in the arguments. And by settingHoldAllComplete you can also inhibit the stripping ofUnevaluated, and prevent the Wolfram Language from using any upvalues it finds associated with the arguments.
There are a number of important interactions in the Wolfram Language 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.
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 withHoldPattern. In general, wheneverHoldPattern[patt] appears within a pattern, this form is taken to be equivalent topatt for the purpose of pattern matching, but the expressionpatt is maintained unevaluated.
| HoldPattern[patt] | equivalent topatt for pattern matching, withpatt kept unevaluated |
One application forHoldPattern is in specifying patterns which can apply to unevaluated expressions, or expressions held in an unevaluated form.
HoldPattern keeps the1+1 from being evaluated, and allows it to match the1+1 on the left‐hand side of the/. operator:
Notice that while functions likeHold prevent evaluation of expressions, they do not affect the manipulation of parts of those expressions with/. and other operators.
As illustrated above, the left‐hand sides of transformation rules such aslhs->rhs are usually evaluated immediately, since the rules are usually applied to expressions which have already been evaluated. The right‐hand side oflhs->rhs is also evaluated immediately. With the delayed rulelhs:>rhs, however, the expressionrhs is not evaluated.
Here are the results of applying the rules. The right‐hand side of the:> rule gets inserted inside theHold without evaluation:
While the left‐hand sides of transformation rules are usually evaluated, the left‐hand 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 left‐hand 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"Non‐Standard Evaluation", a symbol on the left‐hand side of a definition such asx=value is not evaluated. Ifx had previously been assigned a valuey, then if the left‐hand side ofx=value were evaluated, it would turn into the quite unrelated definitiony=value.
If you evaluate the left‐hand side, then you define not the symbolk, but thevaluew[4] of the symbolk:
Although individual symbols that appear on the left‐hand sides of definitions are not evaluated, more complicated expressions are partially evaluated. In an expression such asf[args] on the left‐hand side of a definition, theargs are evaluated.
You can see why the arguments of a function that appears on the left‐hand side of a definition must be evaluated by considering how the definition is used during the evaluation of an expression. As discussed in"Principles of Evaluation", when the Wolfram Language evaluates a function, it first evaluates each of the arguments, then tries to find definitions for the function. As a result, by the time the Wolfram Language 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.
| symbol=value | symbol is not evaluated;value is evaluated |
| symbol:=value | neithersymbol norvalue is evaluated |
| f[args]=value | args are evaluated; left‐hand side as a whole is not |
| f[HoldPattern[arg]]=value | f[arg] is assigned, without evaluatingarg |
| Evaluate[lhs]=value | left‐hand side is evaluated completely |
While in most cases it is appropriate for the arguments of a function that appears on the left‐hand 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 wrapHoldPattern around the parts that you do not want to be evaluated.
The built‐in Wolfram Language iteration functions such asTable andSum evaluate their arguments in a slightly special way.
When evaluating an expression likeTable[f,{i,imax}], the first step, as discussed in "Blocks and Local Values", is to make the value ofi local. Next, the limitimax in the iterator specification is evaluated. The expressionf is maintained in an unevaluated form, but is repeatedly evaluated as a succession of values are assigned toi. When this is finished, the global value ofi is restored.
The functionRandomReal[] is evaluated four separate times here, so four different pseudorandom numbers are generated:
This evaluatesRandomReal[] before feeding it toTable. The result is a list of four identical numbers:
In most cases, it is convenient for the functionf in an expression likeTable[f,{i,imax}] to be maintained in an unevaluated form until specific values have been assigned toi. This is true in particular if a complete symbolic form forf valid for anyi cannot be found.
This definesfac to give the factorial when it has an integer argument, and to giveNaN (standing for "Not a Number") otherwise:
In cases where a complete symbolic form forf with arbitraryi in expressions such asTable[f,{i,imax}]can be found, it is often more efficient to compute this form first, and then feed it toTable. You can do this usingTable[Evaluate[f],{i,imax}].
By insertingEvaluate, you tell the Wolfram Language first to evaluate the sum symbolically, then to iterate overi:
| Table[f,{i,imax}] | keepf unevaluated until specific values are assigned toi |
| Table[Evaluate[f],{i,imax}] | evaluatef first withi left symbolic |
The Wolfram Language provides various ways to set upconditionals, which specify that particular expressions should be evaluated only if certain conditions hold.
| lhs:=rhs/;test | use the definition only iftest evaluates toTrue |
| If[test,then,else] | |
| Which[test1,value1,test2,…] | |
| Switch[expr,form1,value1,form2,…] | compareexpr with each of theformi, giving the value associated with the first form it matches |
| Switch[expr,form1,value1,form2,…,_,def] | usedef as a default value |
| Piecewise[{{value1,test1},…},def] | give the value corresponding to the firsttesti which yieldsTrue |
When you write programs in the Wolfram Language, you will often have a choice between making a single definition whose right‐hand side involves several branches controlled byIf functions, or making several definitions, each controlled by an appropriate/; condition. By using several definitions, you can often produce programs that are both clearer, and easier to modify.
The functionIf provides a way to choose between two alternatives. Often, however, there will be more than two alternatives. One way to handle this is to use a nested set ofIf functions. Usually, however, it is instead better to use functions likeWhich andSwitch.
This defines a function with three regions. UsingTrue as the third test makes this the default case:
This uses the first case in theWhich:
An important point about symbolic systems such as the Wolfram Language is that the conditions you give may yield neitherTrue norFalse. Thus, for example, the conditionx==y does not yieldTrue orFalse unlessx andy have specific values, such as numerical ones.
| If[test,then,else,unknown] | |
| TrueQ[expr] | |
| lhs===rhs or SameQ[lhs,rhs] | |
| lhs=!=rhs or UnsameQ[lhs,rhs] | |
| MatchQ[expr,form] |
The main difference betweenlhs===rhs andlhs==rhs is that=== always returnsTrue orFalse, whereas== can leave its input in symbolic form, representing a symbolic equation, as discussed in"Equations". You should typically use=== when you want to test thestructure of an expression, and== if you want to test mathematical equality. The Wolfram Language pattern matcher effectively uses=== to determine when one literal expression matches another.
In setting up conditionals, you will often need to use combinations of tests, such astest1&&test2&&…. An important point is that the result from this combination of tests will beFalse ifany of thetesti yieldFalse. The Wolfram Language always evaluates thetesti in turn, stopping if any of thetesti yieldFalse.
| expr1&&expr2&&expr3 | evaluate until one of theexpri is found to beFalse |
| expr1||expr2||expr3 | evaluate until one of theexpri is found to beTrue |
Here the first test yieldsFalse, so the second test is not tried. The second test would involve1/0, and would generate an error:
The way that the Wolfram Language evaluates logical expressions allows you to combine sequences of tests where later tests may make sense only if the earlier ones are satisfied. The behavior, which is analogous to that found in languages such as C, is convenient in constructing many kinds of Wolfram Language programs.
The execution of a Wolfram Language program involves the evaluation of a sequence of Wolfram Language expressions. In simple programs, the expressions to be evaluated may be separated by semicolons, and evaluated one after another. Often, however, you need to evaluate expressions several times, in some kind of "loop".
| Do[expr,{i,imax}] | evaluateexpr repetitively, withi varying from1 toimax in steps of1 |
| Do[expr,{i,imin,imax,di}] | evaluateexpr withi varying fromimin toimax in steps ofdi |
| Do[expr,{i,list}] | evaluateexpr withi taking on values fromlist |
| Do[expr,{n}] | evaluateexprn times |
The way iteration is specified inDo is exactly the same as in functions likeTable andSum. Just as in those functions, you can set up several nested loops by giving a sequence of iteration specifications toDo.
Sometimes you may want to repeat a particular operation a certain number of times, without changing the value of an iteration variable. You can specify this kind of repetition inDo just as you can inTable and other iteration functions.
You can put a procedure insideDo:
| Nest[f,expr,n] | applyf toexprn times |
| FixedPoint[f,expr] | start withexpr, and applyf repeatedly until the result no longer changes |
| NestWhile[f,expr,test] |
Do allows you to repeat operations by evaluating a particular expression many times with different values for iteration variables. Often, however, you can make more elegant and efficient programs using the functional programming constructs discussed in"Applying Functions Repeatedly".Nest[f,x,n], for example, allows you to apply a function repeatedly to an expression.
By nesting a pure function, you can get the same result as in the example withDo above:
Nest allows you to apply a function a specified number of times. Sometimes, however, you may simply want to go on applying a function until the results you get no longer change. You can do this usingFixedPoint[f,x].
FixedPoint goes on applying a function until the result no longer changes:
You can useFixedPoint to imitate the evaluation process in the Wolfram Language, or the operation of functions such asexpr//.rules.FixedPoint goes on until two successive results it gets are the same.NestWhile allows you to go on until an arbitrary function no longer yieldsTrue.
When theThrow is encountered, evaluation stops, and the current value ofi is returned as the value of the enclosingCatch:
Throw andCatch provide a flexible way to control the process of evaluation in the Wolfram Language. The basic idea is that whenever aThrow is encountered, the evaluation that is then being done is stopped, and the Wolfram Language immediately returns to the nearest appropriate enclosingCatch.
Scan applies the functionPrint to each successive element in the list, and in the end just returnsNull:
The evaluation ofScan stops as soon asThrow is encountered, and the enclosingCatch returns as its value the argument ofThrow:
The same result is obtained withMap, even thoughMap would have returned a list if its evaluation had not been stopped by encountering aThrow:
You can useThrow andCatch to divert the operation of functional programming constructs, allowing for example the evaluation of such constructs to continue only until some condition has been met. Note that if you stop evaluation usingThrow, then the structure of the result you get may be quite different from what you would have got if you had allowed the evaluation to complete.
Since there is noThrow encountered, the result here is just as before:
Now the evaluation of theNestList is diverted, and the single number given as the argument ofThrow is returned:
Throw andCatch operate in a completely global way: it does not matter how or where aThrow is generated—it will always stop evaluation and return to the enclosingCatch.
This defines a function which generates aThrow when its argument is larger than 10:
NoThrow is generated here:
In small programs, it is often adequate to useThrow[value] andCatch[expr] in their simplest forms. But particularly if you write larger programs that contain many separate pieces, it is usually much better to useThrow[value,tag] andCatch[expr,form]. By keeping the expressionstag andform local to a particular piece of your program, you can then ensure that yourThrow andCatch will also operate only within that piece.
But here it is caught only by the outerCatch:
You can use patterns in specifying the tags which a particularCatch should catch:
You should realize that there is no need for the tag that appears inThrow to be a constant; in general it can be any expression.
Here the innerCatch catches all throws with tags less than 4, and continues theDo. But as soon as the tag reaches 4, the outerCatch is needed:
When you useCatch[expr,form] withThrow[value,tag], the value returned byCatch is simply the expressionvalue given in theThrow. If you useCatch[expr,form,f], however, then the value returned byCatch is insteadf[value,tag].
| While[test,body] | |
| For[start,test,incr,body] | evaluatestart, then repetitively evaluatebody andincr, untiltest fails |
Functions likeDo,Nest, andFixedPoint provide structured ways to make loops in Wolfram Language programs, whileThrow andCatch provide opportunities for modifying this structure. Sometimes, however, you may want to create loops that even from the outset have less structure. And in such cases, you may find it convenient to use the functionsWhile andFor, which perform operations repeatedly, stopping when a specified condition fails to be true.
TheWhile loop continues until the condition fails:
The functionsWhile andFor in the Wolfram Language are similar to the control structureswhile andfor in languages such as C. Notice, however, that there are a number of important differences. For example, the roles of comma and semicolon are reversed in Wolfram LanguageFor loops relative to C language ones.
Here is a more complicatedFor loop. Notice that the loop terminates as soon as the testi^2<10 fails:
In the Wolfram Language, bothWhile andFor always evaluate the loop test before evaluating the body of the loop. As soon as the loop test fails to beTrue,While andFor terminate. The body of the loop is thus only evaluated in situations where the loop test isTrue.
In aWhile orFor loop, or in general in any Wolfram Language procedure, the Wolfram Language expressions you give are evaluated in a definite sequence. You can think of this sequence as defining the "flow of control" in the execution of a Wolfram Language program.
In most cases, you should try to keep the flow of control in your Wolfram Language programs as simple as possible. The more the flow of control depends for example on specific values generated during the execution of the program, the more difficult you will typically find it to understand the structure and operation of the program.
Functional programming constructs typically involve very simple flow of control.While andFor loops are always more complicated, since they are set up to make the flow of control depend on the values of the expressions given as tests. Nevertheless, even in such loops, the flow of control does not usually depend on the values of expressions given in the body of the loop.
In some cases, however, you may need to construct Wolfram Language programs in which the flow of control is affected by values generated during the execution of a procedure or of the body of a loop. One way to do this, which fits in with functional programming ideas, is to useThrow andCatch. But the Wolfram Language also provides various functions for modifying the flow of control which work like in languages such as C.
| Break[] | exit the nearest enclosing loop |
| Continue[] | go to the next step in the current loop |
| Return[expr] | return the valueexpr from a function |
| Goto[name] | go to the elementLabel[name] in the current procedure |
| Throw[value] |
Return[expr] allows you to exit a particular function, returning a value. You can think ofThrow as a kind of nonlocal return which allows you to exit a whole sequence of nested functions. Such behavior can be convenient for handling certain error conditions.
Here is an example of the use ofReturn. This particular procedure could equally well have been written without usingReturn:
When the argument is greater than 5, the firstReturn in the procedure is used:
NoThrow is generated here:
Functions likeContinue[] andBreak[] allow you to "transfer control" to the beginning or end of a loop in a Wolfram Language program. Sometimes you may instead need to transfer control to a particular element in a Wolfram Language procedure. If you give aLabel as an element in a procedure, you can useGoto to transfer control to this element.
Note that you can useGoto in a particular Wolfram Language procedure only when theLabel it specifies occurs as an element of the same Wolfram Language procedure. In general, use ofGoto reduces the degree of structure that can readily be perceived in a program, and therefore makes the operation of the program more difficult to understand.
In many computations you are concerned only with the final result of evaluating the expression given as input. But sometimes you also want to collect expressions that were generated in the course of the evaluation. You can do this usingSow andReap.
This defines a function that can do aSow:
| Sow[val,tag] | sowval with a tag to indicate when to reap |
| Sow[val,{tag1,tag2,…}] | sowval for each of thetagi |
| Reap[expr,form] | reap all values whose tags matchform |
| Reap[expr,{form1,form2,…}] | make separate lists for each of theformi |
| Reap[expr,{form1,…},f] | applyf to each distinct tag and list of values |
The standard way in which the Wolfram System works is to take any expression you give as input, evaluate the expression completely, and then return the result. When you are trying to understand what the Wolfram System is doing, however, it is often worthwhile to look not just at the final result of evaluation, but also at intermediate steps in the evaluation process.
| Trace[expr] | generate a list of all expressions used in the evaluation ofexpr |
| Trace[expr,form] | include only expressions that match the patternform |
Trace[expr] gives a list that includesall the intermediate expressions involved in the evaluation ofexpr. Except in rather simple cases, however, the number of intermediate expressions generated in this way is typically very large, and the list returned byTrace is difficult to understand.
Trace[expr,form] allows you to "filter" the expressions thatTrace records, keeping only those that match the patternform.
This givesall the intermediate expressions generated in the evaluation offac[3]. The result is quite complicated:
You can specify any pattern inTrace:
Trace[expr,form] effectively works by intercepting every expression that is about to be evaluated during the evaluation ofexpr, and picking out those that match the patternform.
If you want to trace "calls" to a function likefac, you can do so simply by tellingTrace to pick out expressions of the formfac[n_]. You can also use patterns likef[n_,2] to pick out calls with particular argument structure.
A typical Wolfram System program, however, consists not only of "function calls" likefac[n], but also of other elements, such as assignments to variables, control structures, and so on. All of these elements are represented as expressions. As a result, you can use patterns inTrace to pick out any kind of Wolfram System program element. Thus, for example, you can use a pattern likek=_ to pick out all assignments to the symbolk.
Trace[expr,form] can pick out expressions that occur at any time in the evaluation ofexpr. The expressions need not, for example, appear directly in the form ofexpr that you give. They may instead occur, say, during the evaluation of functions that are called as part of the evaluation ofexpr.
Trace allows you to monitor intermediate steps in the evaluation not only of functions that you define, but also of some functions that are built into the Wolfram System. You should realize, however, that the specific sequence of intermediate steps followed by built‐in Wolfram System functions depends in detail on their implementation and optimization in a particular version of the Wolfram System.
| Trace[expr,f[___]] | show all calls to the functionf |
| Trace[expr,i=_] | show assignments toi |
| Trace[expr,_=_] | show all assignments |
| Trace[expr,Message[___]] | show messages generated |
Some ways to useTrace.
The functionTrace returns a list that represents the "history" of a Wolfram System computation. The expressions in the list are given in the order that they were generated during the computation. In most cases, the list returned byTrace has a nested structure, which represents the "structure" of the computation.
The basic idea is that each sublist in the list returned byTrace represents the "evaluation chain" for a particular Wolfram System expression. The elements of this chain correspond to different forms of the same expression. Usually, however, the evaluation of one expression requires the evaluation of a number of other expressions, often subexpressions. Each subsidiary evaluation is represented by a sublist in the structure returned byTrace.
The successive forms generated in the simplification ofy+x+y show up as successive elements in its evaluation chain:
There are two basic ways that subsidiary evaluations can be required during the evaluation of a Wolfram System expression. The first way is that the expression may contain subexpressions, each of which has to be evaluated. The second way is that there may be rules for the evaluation of the expression that involve other expressions that themselves must be evaluated. Both kinds of subsidiary evaluations are represented by sublists in the structure returned byTrace.
You often get nested lists when you trace the evaluation of functions that are defined "recursively" in terms of other instances of themselves. The reason is typically that each new instance of the function appears as a subexpression in the expressions obtained by evaluating previous instances of the function.
Thus, for example, with the definitionfac[n_]:=n fac[n-1], the evaluation offac[6] yields the expression6 fac[5], which containsfac[5] as a subexpression.
Each step in the evaluation of any Wolfram System expression can be thought of as the result of applying a particular transformation rule. As discussed in"Associating Definitions with Different Symbols", all the rules that the Wolfram System knows are associated with specific symbols or "tags". You can useTrace[expr,f] to see all the steps in the evaluation ofexpr that are performed using transformation rules associated with the symbolf. In this case,Trace gives not only the expressions to which each rule is applied, but also the results of applying the rules.
In general,Trace[expr,form] picks out all the steps in the evaluation ofexpr whereform matcheseither the expression about to be evaluated,or the tag associated with the rule used.
| Trace[expr,f] | show all evaluations that use transformation rules associated with the symbolf |
| Trace[expr,f|g] | show all evaluations associated with eitherf org |
| Trace[expr,form,TraceOn->oform] | switch on tracing only within forms matchingoform |
| Trace[expr,form,TraceOff->oform] | switch off tracing within any form matchingoform |
Trace[expr,form] allows you to trace expressions matchingform generated at any point in the evaluation ofexpr. Sometimes, you may want to trace only expressions generated during certain parts of the evaluation ofexpr.
By setting the optionTraceOn->oform, you can specify that tracing should be done only during the evaluation of forms that matchoform. Similarly, by settingTraceOff->oform, you can specify that tracing should be switched off during the evaluation of forms that matchoform.
| Trace[expr,lhs->rhs] | find all expressions matchinglhs that arise during the evaluation ofexpr, and replace them withrhs |
A powerful aspect of the Wolfram SystemTrace function is that the object it returns is basically a standard Wolfram System expression that you can manipulate using other Wolfram System functions. One important point to realize, however, is thatTrace wraps all expressions that appear in the list it produces withHoldForm to prevent them from being evaluated. TheHoldForm is not displayed in standard Wolfram System output format, but it is still present in the internal structure of the expression.
The expressions are wrapped withHoldForm to prevent them from evaluating:
In standard Wolfram System output format, it is sometimes difficult to tell which lists are associated with the structure returned byTrace, and which are expressions being evaluated:
When you use a transformation rule inTrace, the result is evaluated before being wrapped withHoldForm:
For sophisticated computations, the list structures returned byTrace can be quite complicated. When you useTrace[expr,form],Trace will include as elements in the lists only those expressions that match the patternform. But whatever pattern you give, the nesting structure of the lists remains the same.
You can set the optionTraceDepth->n to tellTrace to include only lists nested at mostn levels deep. In this way, you can often pick out the "big steps" in a computation, without seeing the details. Note that by settingTraceDepth orTraceOff you can avoid looking at many of the steps in a computation, and thereby significantly speed up the operation ofTrace for that computation.
| Trace[expr,form,TraceDepth->n] | trace the evaluation ofexpr, ignoring steps that lead to lists nested more thann levels deep |
When you useTrace[expr,form], you get a list of all the expressions that matchform produced during the evaluation ofexpr. Sometimes it is useful to see not only these expressions, but also the results that were obtained by evaluating them. You can do this by setting the optionTraceForward->True inTrace.
This shows not only expressions that matchfac[_], but also the results of evaluating those expressions:
Expressions picked out usingTrace[expr,form] typically lie in the middle of an evaluation chain. By settingTraceForward->True, you tellTrace to include also the expression obtained at the end of the evaluation chain. If you setTraceForward->All,Trace will includeall the expressions that occur after the expression matchingform on the evaluation chain.
WithTraceForward->All, all elements on the evaluation chain after the one that matchesfac[_] are included:
By setting the optionTraceForward, you can effectively see what happens to a particular form of expression during an evaluation. Sometimes, however, you want to find out not what happens to a particular expression, but instead how that expression was generated. You can do this by setting the optionTraceBackward. WhatTraceBackward does is to show you whatpreceded a particular form of expression on an evaluation chain.
TraceForward andTraceBackward allow you to look forward and backward in a particular evaluation chain. Sometimes, you may also want to look at the evaluation chains within which the particular evaluation chain occurs. You can do this usingTraceAbove. If you set the optionTraceAbove->True, thenTrace will include the initial and final expressions in all the relevant evaluation chains. WithTraceAbove->All,Trace includes all the expressions in all these evaluation chains.
This includes the initial and final expressions in all evaluation chains that contain the chain that contains120:
| Trace[expr,form,opts] | trace the evaluation ofexpr using the specified options |
| TraceForward->True | include the final expression in the evaluation chain containingform |
| TraceForward->All | include all expressions followingform in the evaluation chain |
| TraceBackward->True | include the first expression in the evaluation chain containingform |
| TraceBackward->All | include all expressions precedingform in the evaluation chain |
| TraceAbove->True | include the first and last expressions in all evaluation chains that contain the chain containingform |
| TraceAbove->All | include all expressions in all evaluation chains that contain the chain containingform |
The basic way thatTrace[expr,…] works is to intercept each expression encountered during the evaluation ofexpr, and then to use various criteria to determine whether this expression should be recorded. Normally, however,Trace intercepts expressions onlyafter function arguments have been evaluated. By settingTraceOriginal->True, you can getTrace also to look at expressionsbefore function arguments have been evaluated.
The list structure produced byTrace normally includes only expressions that constitute steps in non‐trivial evaluation chains. Thus, for example, individual symbols that evaluate to themselves are not normally included. Nevertheless, if you setTraceOriginal->True, thenTrace looks at absolutely every expression involved in the evaluation process, including those that have trivial evaluation chains.
In this case,Trace includes absolutely all expressions, even those with trivial evaluation chains:
option name | default value | |
| TraceForward | False | whether to show expressions followingform in the evaluation chain |
| TraceBackward | False | whether to show expressions precedingform in the evaluation chain |
| TraceAbove | False | whether to show evaluation chains leading to the evaluation chain containingform |
| TraceOriginal | False | whether to look at expressions before their heads and arguments are evaluated |
Additional options forTrace.
When you useTrace to study the execution of a program, there is an issue about how local variables in the program should be treated. As discussed in"How Modules Work", Wolfram System scoping constructs such asModule create symbols with new names to represent local variables. Thus, even if you called a variablex in the original code for your program, the variable may effectively be renamedx$nnn when the program is executed.
Trace[expr,form] is set up so that by default a symbolx that appears inform will match all symbols with names of the formx$nnn that arise in the execution ofexpr. As a result, you can for example useTrace[expr,x=_] to trace assignment to all variables, local and global, that were namedx in your original program.
| Trace[expr,form,MatchLocalNames->False] | |
include all steps in the execution ofexpr that matchform, with no replacements for local variable names allowed | |
In some cases, you may want to trace only the global variablex, and not any local variables that were originally namedx. You can do this by setting the optionMatchLocalNames->False.
The functionTrace performs a complete computation, then returns a structure that represents the history of the computation. Particularly in very long computations, it is however sometimes useful to see traces of the computation as it proceeds. The functionTracePrint works essentially likeTrace, except that it prints expressions when it encounters them, rather than saving up all of the expressions to create a list structure.
The sequence of expressions printed byTracePrint corresponds to the sequence of expressions given in the list structure returned byTrace. Indentation in the output fromTracePrint corresponds to nesting in the list structure fromTrace. You can use theTrace optionsTraceOn,TraceOff andTraceForward inTracePrint. However, sinceTracePrint produces output as it goes, it cannot support the optionTraceBackward. In addition,TracePrint is set up so thatTraceOriginal is effectively always set toTrue.
| Trace[expr,…] | trace the evaluation ofexpr, returning a list structure containing the expressions encountered |
| TracePrint[expr,…] | trace the evaluation ofexpr, printing the expressions encountered |
| TraceDialog[expr,…] | trace the evaluation ofexpr, initiating a dialog when each specified expression is encountered |
| TraceScan[f,expr,…] |


The functionTraceDialog effectively allows you to stop in the middle of a computation and interact with the Wolfram System environment that exists at that time. You can, for example, find values of intermediate variables in the computation, and even reset those values. There are, however, a number of subtleties, mostly associated with pattern and module variables.
WhatTraceDialog does is to call the functionDialog on a sequence of expressions. TheDialog function is discussed in detail in"Dialogs". When you callDialog, you are effectively starting a subsidiary Wolfram System session with its own sequence of input and output lines.
In general, you may need to apply arbitrary functions to the expressions you get while tracing an evaluation.TraceScan[f,expr,…] appliesf to each expression that arises. The expression is wrapped withHoldForm to prevent it from evaluating.
InTraceScan[f,expr,…], the functionf is applied to expressions before they are evaluated.TraceScan[f,expr,patt,fp] appliesf before evaluation, andfp after evaluation.
Throughout any computation, the Wolfram System maintains anevaluation stack containing the expressions it is currently evaluating. You can use the functionStack to look at the stack. This means, for example, that if you interrupt the Wolfram System in the middle of a computation, you can useStack to find out what the Wolfram System is doing.
The expression that the Wolfram System most recently started to evaluate always appears as the last element of the evaluation stack. The previous elements of the stack are the other expressions whose evaluation is currently in progress.
Thus at the point whenx is being evaluated, the stack associated with the evaluation of an expression likef[g[x]] will have the form{f[g[x]],g[x],x}.
Stack[_] gives the expressions that are being evaluated at the time when it is called, in this case including thePrint function:
Stack[] gives the tags associated with the evaluations that are being done when it is called:
In general, you can think of the evaluation stack as showing what functions called what other functions to get to the point the Wolfram System is at in your computation. The sequence of expressions corresponds to the first elements in the successively nested lists returned byTrace with the optionTraceAbove set toTrue.
| Stack[] | give a list of the tags associated with evaluations that are currently being done |
| Stack[_] | give a list of all expressions currently being evaluated |
| Stack[form] | include only expressions which matchform |
It is rather rare to callStack directly in your main Wolfram System session. More often, you will want to callStack in the middle of a computation. Typically, you can do this from within a dialog, or subsidiary session, as discussed in"Dialogs".


In the simplest cases, the Wolfram System evaluation stack is set up to recordall expressions currently being evaluated. Under some circumstances, however, this may be inconvenient. For example, executingPrint[Stack[]] will always show a stack withPrint as the last function.
The functionStackInhibit allows you to avoid this kind of problem.StackInhibit[expr] evaluatesexpr without modifying the stack.
Functions likeTraceDialog automatically callStackInhibit each time they start a dialog. This means thatStack does not show functions that are called within the dialog, only those outside.
| StackInhibit[expr] | evaluateexpr without modifying the stack |
| StackBegin[expr] | evaluateexpr with a fresh stack |
| StackComplete[expr] | evaluateexpr with intermediate expressions in evaluation chains included on the stack |
By usingStackInhibit andStackBegin, you can control which parts of the evaluation process are recorded on the stack.StackBegin[expr] evaluatesexpr, starting a fresh stack. This means that during the evaluation ofexpr, the stack does not include anything outside theStackBegin. Functions likeTraceDialog[expr,…] callStackBegin before they begin evaluatingexpr, so that the stack shows howexpr is evaluated, but not howTraceDialog was called.
Stack normally shows you only those expressions that are currently being evaluated. As a result, it includes only the latest form of each expression. Sometimes, however, you may find it useful also to see earlier forms of the expressions. You can do this usingStackComplete.
WhatStackComplete[expr] effectively does is to keep on the stack the complete evaluation chain for each expression that is currently being evaluated. In this case, the stack corresponds to the sequence of expressions obtained fromTrace with the optionTraceBackward->All as well asTraceAbove->True.
The general principle that the Wolfram Language follows in evaluating expressions is to go on applying transformation rules until the expressions no longer change. This means, for example, that if you make an assignment likex=x+1, the Wolfram Language should go into an infinite loop. In fact, the Wolfram Language stops after a definite number of steps, determined by the value of the global variable$RecursionLimit. You can always stop the Wolfram Language earlier by explicitly interrupting it.
This assignment could cause an infinite loop. The Wolfram Language stops after a number of steps determined by$RecursionLimit:

| $RecursionLimit | maximum depth of the evaluation stack |
| $IterationLimit | maximum length of an evaluation chain |
Here is a circular definition, whose evaluation is stopped by$IterationLimit:


The variables$RecursionLimit and$IterationLimit control the two basic ways that an evaluation can become infinite in the Wolfram Language.$RecursionLimit limits the maximum depth of the evaluation stack, or equivalently, the maximum nesting depth that would occur in the list structure produced byTrace.$IterationLimit limits the maximum length of any particular evaluation chain, or the maximum length of any single list in the structure produced byTrace.
$RecursionLimit and$IterationLimit are by default set to values that are appropriate for most computations, and most computer systems. You can, however, reset these variables to any integer (above a lower limit), or toInfinity. Note that on most computer systems, you should never set$RecursionLimit=Infinity, as discussed in"Memory Management".

The variablei was incremented to 37 rather than 40 asCompoundExpression,t andPlus are also in the evaluation chain:

In this case, no complicated structure is built up, and the computation is stopped by$IterationLimit:

It is important to realize that infinite loops can take up not only time but also computer memory. Computations limited by$IterationLimit do not normally build up large intermediate structures. But those limited by$RecursionLimit often do. In many cases, the size of the structures produced is a linear function of the value of$RecursionLimit. But in some cases, the size can grow exponentially, or worse, with$RecursionLimit.
An assignment likex=x+1 is obviously circular. When you set up more complicated recursive definitions, however, it can be much more difficult to be sure that the recursion terminates, and that you will not end up in an infinite loop. The main thing to check is that the right‐hand sides of your transformation rules will always be different from the left‐hand sides. This ensures that evaluation will always "make progress", and the Wolfram Language will not simply end up applying the same transformation rule to the same expression over and over again.
Some of the trickiest cases occur when you have rules that depend on complicated/; conditions (see"Putting Constraints on Patterns"). One particularly awkward case is when the condition involves a "global variable". The Wolfram Language may think that the evaluation is finished because the expression did not change. However, a side effect of some other operation could change the value of the global variable, and so should lead to a new result in the evaluation. The best way to avoid this kind of difficulty is not to use global variables in/; conditions. If all else fails, you can typeUpdate[s] to tell the Wolfram Language to update all expressions involvings.Update[] tells the Wolfram Language to update absolutely all expressions.
"Interrupting Calculations" describes how you can interrupt a Wolfram Language computation by pressing appropriate keys on your keyboard.
In some cases, you may want to simulate such interrupts from within a Wolfram Language program. In general, executingInterrupt[] has the same effect as pressing interrupt keys. On a typical system, a menu of options is displayed, as discussed in"Interrupting Calculations".
| Interrupt[] | interrupt a computation |
| Abort[] | abort a computation |
| CheckAbort[expr,failexpr] | evaluateexpr and return the result, orfailexpr if an abort occurs |
| AbortProtect[expr] | evaluateexpr, masking the effect of aborts until the evaluation is complete |
The functionAbort[] has the same effect as interrupting a computation, and selecting theabort option in the interrupt menu.
You can useAbort[] to implement an "emergency stop" in a program. In almost all cases, however, you should try to use functions likeReturn andThrow, which lead to more controlled behavior.
If you abort at any point during the evaluation of a Wolfram Language expression, the Wolfram Language normally abandons the evaluation of the whole expression, and returns the value$Aborted.
You can, however, "catch" aborts using the functionCheckAbort. If an abort occurs during the evaluation ofexpr inCheckAbort[expr,failexpr], thenCheckAbort returnsfailexpr, but the abort propagates no further. Functions likeDialog useCheckAbort in this way to contain the effect of aborts.
When you construct sophisticated programs in the Wolfram Language, you may sometimes want to guarantee that a particular section of code in a program cannot be aborted, either interactively or by callingAbort. The functionAbortProtect allows you to evaluate an expression, saving up any aborts until after the evaluation of the expression is complete.
TheCheckAbort sees the abort, but does not propagate it further:
Even insideAbortProtect,CheckAbort will see any aborts that occur, and will return the appropriatefailexpr. Unless thisfailexpr itself containsAbort[], the aborts will be "absorbed" by theCheckAbort.
If you make a definition likef[x_]:=xSin[x], the Wolfram Language will store the expressionxSin[x] in a form that can be evaluated for anyx. Then when you give a particular value forx, the Wolfram Language substitutes this value intoxSin[x], and evaluates the result. The internal code that the Wolfram Language uses to perform this evaluation is set up to work equally well whether the value you give forx is a number, a list, an algebraic object, or any other kind of expression.
Having to take account of all these possibilities inevitably makes the evaluation process slower. However, if the Wolfram Language couldassume thatx will be a machine number, then it could avoid many steps, and potentially evaluate an expression likexSin[x] much more quickly.
UsingCompile, you can constructcompiled functions in the Wolfram Language, which evaluate Wolfram Language expressions assuming that all the parameters which appear are numbers (or logical variables).Compile[{x1,x2,…},expr] takes an expressionexpr and returns a "compiled function" which evaluates this expression when given arguments
.
.In general,Compile creates aCompiledFunction object which contains a sequence of simple instructions for evaluating the compiled function. The instructions are chosen to be close to those found in the machine code of a typical computer, and can thus be executed quickly.
| Compile[{x1,x2,…},expr] | create a compiled function which evaluatesexpr for numerical values of thexi |
This creates a compiled function for evaluatingxSin[x]:
Compile is useful in situations where you have to evaluate a particular numerical or logical expression many times. By taking the time to callCompile, you can get a compiled function which can be executed more quickly than an ordinary Wolfram Language function.
For simple expressions such asxSin[x], there is usually little difference between the execution speed for ordinary and compiled functions. However, as the size of the expressions involved increases, the advantage of compilation also increases. For large expressions, compilation can speed up execution by a factor as large as 20.
Compilation makes the biggest difference for expressions containing a large number of simple, say arithmetic, functions. For more complicated functions, such asBesselK orEigenvalues, most of the computation time is spent executing internal Wolfram Language algorithms, on which compilation has no effect.
This creates a compiled function for finding values of the tenth Legendre polynomial.Evaluate tells the Wolfram Language to construct the polynomial explicitly before doing compilation:
Even though you can use compilation to speed up numerical functions that you write, you should still try to use built‐in Wolfram Language functions whenever possible. Built‐in functions will usually run faster than any compiled Wolfram Language programs you can create. In addition, they typically use more extensive algorithms, with more complete control over numerical precision and so on.
You should realize that built‐in Wolfram Language functions quite often themselves useCompile. Thus, for example,NIntegrate by default automatically usesCompile on the expression you tell it to integrate. Similarly, functions likePlot andPlot3D useCompile on the expressions you ask them to plot. Built‐in functions that useCompile typically have the optionCompiled. SettingCompiled->False tells the functions not to useCompile.
| Compile[{{x1,t1},{x2,t2},…},expr] | compileexpr assuming thatxi is of typeti |
| Compile[{{x1,t1,n1},{x2,t2,n2},…},expr] | |
compileexpr assuming thatxi is a rankni array of objects each of typeti | |
| Compile[vars,expr,{{p1,pt1},…}] | compileexpr, assuming that subexpressions which matchpi are of typepti |
| _Integer | machine‐size integer |
| _Real | machine‐precision approximate real number |
| _Complex | machine‐precision approximate complex number |
| True|False | logical variable |
Compile works by making assumptions about the types of objects that occur in evaluating the expression you give. The default assumption is that all variables in the expression are approximate real numbers.
Compile nevertheless also allows integers, complex numbers and logical variables (True orFalse), as well as arrays of numbers. You can specify the type of a particular variable by giving a pattern which matches only values that have that type. Thus, for example, you can use the pattern_Integer to specify the integer type. Similarly, you can useTrue|False to specify a logical variable that must be eitherTrue orFalse.
The types thatCompile handles correspond essentially to the types that computers typically handle at a machine‐code level. Thus, for example,Compile can handle approximate real numbers that have machine precision, but it cannot handle arbitrary‐precision numbers. In addition, if you specify that a particular variable is an integer,Compile generates code only for the case when the integer is of "machine size", typically between
.
.When the expression you ask to compile involves only standard arithmetic and logical operations,Compile can deduce the types of objects generated at every step simply from the types of the input variables. However, if you call other functions,Compile will typically not know what type of value they return. If you do not specify otherwise,Compile assumes that any other function yields an approximate real number value. You can, however, also give an explicit list of patterns, specifying what type to assume for an expression that matches a particular pattern.
The idea ofCompile is to create a function which is optimized for certain types of arguments.Compile is nevertheless set up so that the functions it creates work with whatever types of arguments they are given. When the optimization cannot be used, a standard Wolfram Language expression is evaluated to find the value of the function.
The compiled code cannot be used, so the Wolfram Language prints a warning, then just evaluates the original symbolic expression:

The compiled code generated byCompile must make assumptions not only about the types of arguments you will supply, but also about the types of all objects that arise during the execution of the code. Sometimes these types depend on the actualvalues of the arguments you specify. Thus, for example,Sqrt[x] yields a real number result for realx ifx is not negative, but yields a complex number ifx is negative.
Compile always makes a definite assumption about the type returned by a particular function. If this assumption turns out to be invalid in a particular case when the code generated byCompile is executed, then the Wolfram Language simply abandons the compiled code in this case, and evaluates an ordinary Wolfram Language expression to get the result.
The compiled code does not expect a complex number, so the Wolfram Language has to revert to explicitly evaluating the original symbolic expression:

An important feature ofCompile is that it can handle not only mathematical expressions, but also various simple Wolfram Language programs. Thus, for example,Compile can handle conditionals and control flow structures.
In all cases,Compile[vars,expr] holds its arguments unevaluated. This means that you can explicitly give a "program" as the expression to compile.
[8]ページ先頭
©2009-2025 Movatter.jp



































































































