2.6.12 Advanced Topic: The Evaluation Stack
Throughout any computation, Mathematica maintains an evaluation stack containing the expressions it is currently evaluating. You can use the function Stack to look at the stack. This means, for example, that if you interrupt Mathematica in the middle of a computation, you can use Stack to find out what Mathematica is doing.
The expression that Mathematica 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 when x is being evaluated, the stack associated with the evaluation of an expression like f [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 the Print function.
In:= f[g[ Print[Stack[_]] ]] ;
Stack[ ] gives the tags associated with the evaluations that are being done when it is called.
In:= f[g[ Print[Stack[ ]] ]] ;
In general, you can think of the evaluation stack as showing what functions called what other functions to get to the point Mathematica is at in your computation. The sequence of expressions corresponds to the first elements in the successively nested lists returned by Trace with the option TraceAbove set to True.
Looking at the evaluation stack.
It is rather rare to call Stack directly in your main Mathematica session. More often, you will want to call Stack in the middle of a computation. Typically, you can do this from within a dialog, or subsidiary session, as discussed in Section 2.14.2.
Here is the standard recursive definition of the factorial function.
In:= fac = 1; fac[n_] := n fac[n-1]
This evaluates fac, starting a dialog when it encounters fac.
In:= TraceDialog[fac, fac]
This shows what objects were being evaluated when the dialog was started.
In:= Stack[ ]
This ends the dialog.
In:= Return[ ]
In the simplest cases, the Mathematica evaluation stack is set up to record all expressions currently being evaluated. Under some circumstances, however, this may be inconvenient. For example, executing Print[Stack[ ]] will always show a stack with Print as the last function.
The function StackInhibit allows you to avoid this kind of problem. StackInhibit[expr] evaluates expr without modifying the stack.
StackInhibit prevents Print from being included on the stack.
In:= f[g[ StackInhibit[Print[Stack[ ]]] ]] ;
Functions like TraceDialog automatically call StackInhibit each time they start a dialog. This means that Stack does not show functions that are called within the dialog, only those outside.
Controlling the evaluation stack.
By using StackInhibit and StackBegin, you can control which parts of the evaluation process are recorded on the stack. StackBegin[expr] evaluates expr, starting a fresh stack. This means that during the evaluation of expr, the stack does not include anything outside the StackBegin. Functions like TraceDialog[expr, ... ] call StackBegin before they begin evaluating expr, so that the stack shows how expr is evaluated, but not how TraceDialog was called.
StackBegin[expr] uses a fresh stack in the evaluation of expr.
In:= f[ StackBegin[ g[h[ StackInhibit[Print[Stack[ ]]] ]] ] ]
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 using StackComplete.
What StackComplete[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 from Trace with the option TraceBackward -> All as well as TraceAbove -> True.