Needs["traceUtils`"]

tracePrintIndexed

The function tracePrintIndexed is much like the function TracePrint with some additional features:

o Step numbers printed before each step improve readability and can be used to "zoom in" on a portion of a shallow trace.

o A delimiter makes clear which steps begin evaluation sub-chains and which steps result from rewriting other steps.

o Trivial evaluation chains can be ignored.

o Options that resemble TraceOn and TraceOff but that work inside of each other are available.

basics

In its simplest usage, typing tracePrintIndexed[expr] produces output similar to TracePrint[expr], but with a step number  assigned to each step in the evaluation being traced:

{a1, a2, a3} = {b1, b2, b3};

TracePrint[ a1[a2[a3]] ];

tracePrintIndexed[ a1[a2[a3]] ]

Like TracePrint, tracePrintIndexed indents each step that it prints according to the trace level  of the step. When a step is the first member of an evaluation chain, the step number is followed by a ":". Otherwise, the step number is followed by a "$", which indicates that the step is a replacement for the previous step on the same level. In the last example, steps 2 and 4 are parts of step 1, and steps 5 and 7 are parts of step 4. Steps 3, 6, 8, 9, and 10, on the other hand, are the results of rewriting steps 2, 5, 7, 4, and 1, respectively.

The option skipTrivialChains

The evaluation of a1[a2[a3]] traced above was unusual in that every part of the expression was eventually replaced.  In most evaluations, a substantial fraction of the steps belong to trivial evaluation chains in which Mathematica  is examining parts of an expression which end up evaluating to themselves. By default, the function tracePrintIndexed omits printing any steps belonging to such trivial chains. You can tell from the step numbers how many intermediate steps have been skipped:

tracePrintIndexed[ 2 (3 + 4 + 5) ]

The printing of steps in trivial evaluation chains is controlled by an option skipTrivialChains whose default value is  True. To see all the steps in a trace, set  skipTrivialChains to be False:

tracePrintIndexed[
  2 (3 + 4 + 5), 
  skipTrivialChains -> False ]

One advantage of showing all of the steps in a trace is that it clarifies the systematic evaluation algorithm that the kernel is using. See the sections on the evaluation of expressions in the Mathematica  book for more information. For the experienced user, however, we are guessing that the extra steps are a distraction. Here is one more example:

tracePrintIndexed[Transpose[{{1, 3}, {5, 7}}] ]

tracePrintIndexed[
  Transpose[{{1, 3}, {5, 7}}],
  skipTrivialChains -> False ]

You can of course change the default values for skipTrivialChains and other options of tracePrintIndexed  to suite yourself.

The option printCondition

The function tracePrintIndexed has an option printCondition whose default value is True.   If  "printCondition -> expr" is supplied as an optional argument to tracePrintIndexed, the value of expr will be recomputed at each step, and the step will be printed only if the result is True.  The  expression expr may involve one or more of three special symbols: $step, $stepNumber, and $traceLevel, which represent the step being considered, its step number, and its trace level, respectively.  Note: as in all tracing functions, each step comes wrapped in  HoldForm to prevent evaluation.

Example using $step

One use of $step in printCondition is to pick out only those steps which match a pattern. Here is an example with a recursive factorial function.

fac[n_] := n fac[-1 + n];
fac[1] = 1;

tracePrintIndexed[
  fac[5],
  printCondition -> 
    MatchQ[
      $step,
      HoldForm[fac[_]]] ]

Example using $traceLevel

One use of $traceLevel in printCondition is to print only the "shallow" steps in a trace. Here is an example with a recursive function for computing Fibonacci numbers.

fib[n_] := fib[-2 + n] + fib[-1 + n];
fib[0] = fib[1] = 1;

tracePrintIndexed[
  fib[5], 
  printCondition ->
    $traceLevel < 4]

Example using $stepNumber

One use of $stepNumber in printCondition is to "zoom in" on a portion of a previous shallow trace. Here we examine the reduction of fib[-2 + 3] + fib[-1 + 3] to 3 in the previous example.

tracePrintIndexed[
  fib[5], 
  printCondition ->
    14 <= $stepNumber <= 56]

Contrast with TracePrint/TraceScan options

tracePrintIndexed works by calling TraceScan. Optional arguments understood by TraceScan can therefore be given to tracePrintIndexed. (Exception: the option TraceOn is disabled for technical reasons.) Passing optional arguments to TraceScan in this way, however, will affect the assignment of step numbers because tracePrintIndexed can only assign numbers to steps that are acknowledged by TraceScan.

tracePrintIndexed[
  fac[5], 
  fac[_] ]

(* Seen previously *)
tracePrintIndexed[
  fac[5],
  printCondition -> 
    MatchQ[
      $step,
      HoldForm[fac[_]]] ]

tracePrintIndexed[
  fib[5],
  TraceDepth -> 2]

(* Seen previously *)
tracePrintIndexed[
  fib[5], 
  printCondition ->
    $traceLevel < 4]

The options suppressForm, suppressWhole, and unsuppressForm.

suppressForm

In addition to skipping trivial chains and testing a print condition, tracePrintIndexed may be inhibited from printing certain steps by entering suppress mode.  If  "suppressForm -> patt"  is given as an optional argument to tracePrintIndexed, suppress mode will be entered whenever a step matching the pattern patt is encountered, and exited when the evaluation chain of that step is complete. Both the step that is matched and its final value will be printed, but nothing in between.  suppressForm is similar to, but not quite the same as, TraceOff.

tracePrintIndexed[
  log1[fac[2] x], 
  TraceOff -> fac[_]]

tracePrintIndexed[
  log1[fac[2] x], 
  suppressForm -> fac[_] ]

unsuppressForm with suppressWhole -> True

Supplying the option assignment suppressWhole -> True instructs tracePrintIndexed to begin the trace in suppress mode.  No steps will be printed unless a value patt for the option unsuppressForm is also supplied.  In that case, suppress mode is exited when a step matching patt is encountered, and re-entered when the evaluation chain of that step is complete. Used in this way, unsuppressForm is a substitute for TraceOn.

tracePrintIndexed[
  log1[fac[2] x], 
  suppressWhole -> True,
  unsuppressForm -> fac[_] ]

suppressForm and unsuppressForm together

Unlike TraceOff and TraceOn, the options suppressForm and unsuppressForm work inside of each other:

f1[x_] := {{{g1[-1 + x]}}};
g1[x_] := f1[x];
g1[1] = 1;

tracePrintIndexed[
  {f1[3]},  
  suppressForm -> f1[_],
  unsuppressForm -> g1[_] ]

In the above example, suppress mode is entered at step 3 by a match with suppressForm, exited at step 12 by a match with unsuppressForm, entered at step 20 by another match with suppressForm, and exited at step 29 by another match with suppressForm. tracePrintIndexed backs into, out of, into, and out of suppress mode as the evaluation chains of the matched steps are completed in steps 37, 40, 40, and 43.

The options suppressForm and unsuppressForm also work inside of each other with suppressWhole -> True:

tracePrintIndexed[
  {f1[3]},  
  suppressForm -> f1[_],
  unsuppressForm -> g1[_],
  suppressWhole -> True ]

The option indentOutput.

tracePrintIndexed has an option named indentOutput whose default value is True. Setting indentOutput -> False results in printing the numerical value of the trace level between the step number and the delimiter ":" or "$" rather than indenting the step:

log1[x_ y_] := log1[x] + log1[y];

tracePrintIndexed[ 
  log1[a b c d] ]

tracePrintIndexed[ 
  log1[a b c d],
  indentOutput -> False ]

Setting indentOutput -> False is most likely to be desirable when trace levels and step lengths get large enough so that the indenting is not very helpful. Here is an example where, if your terminal line contains no more than 80 characters or so, the value of indenting should be questionable:

foo[n_] := (Range[n]; foo[1+n]);
foo[25] := Null;

tracePrintIndexed[foo[5], 
  printCondition ->
    MatchQ[$step, HoldForm[{___}]] &&
    $traceLevel > 15]

tracePrintIndexed[foo[5],
  indentOutput -> False, 
  printCondition ->
    MatchQ[$step, HoldForm[{___}]] &&
    $traceLevel > 15]

Technical note: To avoid double spacing of multi-line steps on our Macintosh, we had to set Format[LineBreak[_]] = "" in the definition of tracePrintIndexed. We don't know if this is right for all machines. You may want to change this if you find that long steps are not being properly broken up into readable lines.

The option doubleSpace.

Setting doubleSpace -> True instructs tracePrintIndexed to print a blank line between every step. This may improve readability when the evaluation being traced involves powers or products.

tracePrintIndexed[
  (3 10)/5 + 3^5]

tracePrintIndexed[
  (3 10)/5 + 3^5,
  doubleSpace -> True]

tracePrintStack

The function tracePrintStack prints the evaluation stack as well as the current step at each stage of a trace. Using the option printCondition as described below, you can print the stack at any one particular step in an evaluation.

For anyone interested in learning how the evaluation stack works, we highly recommend running tracePrintStack on some simple examples.

basics

The printing format used for each step is the same as the format used by tracePrintIndexed with indentOutput -> False.

a1 = b1;
a2 = b2;

tracePrintStack[ a1[a2] ]

tracePrintStack supports only two options: useCompleteStack and printCondition. Other optional arguments will be ignored.

the option useCompleteStack

With useCompleteStack -> True, tracePrintStack displays the "complete" evaluation stack:

a1 = b1;
b1 = c1;

tracePrintStack[ a1 ]

tracePrintStack[ a1, useCompleteStack -> True ]

the option printCondition.

When used with tracePrintStack, the option printCondition behaves exactly as it does for tracePrintIndexed. The symbols $step, $stepNumber, and $traceLevel have the same meanings. In particular, you can make use of $stepNumber to print the evaluation stack at one particular step in a trace:

fac[n_] := n fac[-1 + n];
fac[1] = 1;

tracePrintIndexed[ fac[4] ]

tracePrintStack[
  fac[4], 
  printCondition -> $stepNumber == 37 ]

tracePrintStack[
  fac[4], 
  printCondition -> $stepNumber == 37,
  useCompleteStack -> True ]

Copyright  1995 by Christopher R. Stover