Skip to content

New Trace Facilities in J 3.03

Vector 13:3, page 52

implementations development practice

Transcribed from the printed issue; not yet reviewed. Read it in the PDF of the issue, page 52

Acknowledgments

I am indebted to Richard Brown and Cliff Reiter for suggestions leading to facilities described herein.

Extension to Error Text

The name of the current verb (if any) is displayed along with the name of the error; having the current name makes it much easier to isolate errors in nested function calls.

Example 0:

   mean=: sum % #

   mean i.9
|value error: sum                           the current verb is sum
|       mean i.9

   sum=: +/
   mean i.9
4

   mean 'asdf'
|domain error: sum
|       mean'asdf'

   (+/ % #) 'asdf'
|domain error                               the current verb is anonymous
|       (+/%#)'asdf'

Example 1:

   mean=: 3 : '(sum y.) % # y.'

   mean i.9
|value error: sum
|   (     sum y.)%#y.

   sum=: 3 : '+/y.'

   mean i.9
4

   mean 'asdf'
|domain error: sum
|       +/y.

Trace

The conjunction 13!:16 controls tracing.

   u 13!:16 n
   (r,c) 13!:16 n

The right argument n specifies the maximum level of function call to be traced: 0 means no trace; 1 means immediate execution only; _ means trace everything; etc. The left argument can be a verb to be used for displaying arrays in the trace (and is not itself traced during tracing). It may also be integers r,c, whence the system default display is used, clipped to r rows and c columns. (Two numbers suffice as clipping parameters because the output of an n-dimensional array is 2-dimensional on the screen.) Finally, it may be the empty vector, whence the current trace level and display controls are shown. The result is i.0 0.

The following sets of examples illustrate the use of the trace facility.

  1. Controlling Trace
  2. Tracing
  3. Tacit Verbs
  4. Explicit Verbs
  5. Operators
  6. Errors

Example 0: Controlling Trace

trace=: 13!:16
lr   =: 3 : '5!:5<''y.'''            linear display of an array

_ _ trace _       trace everything; display everything
9 trace 1         trace immediate execution only; display maximum of 9 rows
": trace n        same as _ _ trace n
lr trace n        linear display of trace output

Example 1: Tracing

Tracing provides information on results within a line; the action labels, "0 monad", "1 monad", "9 paren", etc., are from the parse table in Section II E of the J Introduction and Dictionary, and reflect the activities of the interpreter with high fidelity.

The commentary on the right is not part of the trace.

   _ _ (13!:16) _                       trace everything; display everything

   i.4
 -------------- 0 monad ------          action
 i.                                     verb
 4                                      argument
 0 1 2 3                                result
 ==============================         end of parse
0 1 2 3                                 result of immediate exec.

   n=. # 'Cogito, ergo sum.'
 -------------- 0 monad ------
 #
 Cogito, ergo sum.
 17
 -------------- 8 is ---------
 n                                      As usual, the result of
 =.                                     immediate execution is not
 17                                     displayed if the last action
 ==============================         was assignment.

   (i.2 4) +/ .* *: 5 * 10 20 30 40
 -------------- 2 dyad -------
 5                                      left argument
 *                                      verb
 10 20 30 40                            right argument
 50 100 150 200                         result

 -------------- 0 monad ------
 i.                                     verb
 2 4                                    argument
 0 1 2 3                                | result
 4 5 6 7                                |

 -------------- 9 paren ------
 0 1 2 3
 4 5 6 7

 -------------- 3 adverb -----
 +
 /
 +/

 -------------- 4 conj -------
 +/
  .
 *
 +/ .*

 -------------- 1 monad ------          Words to the left of *:
 *:                                     are parsed first because an
 50 100 150 200                         operator may "grab" a
 2500 10000 22500 40000                 verb.

 -------------- 2 dyad -------
 0 1 2 3                                | left argument
 4 5 6 7                                |
 +/ .*                                  verb
 2500 10000 22500 40000                 right argument
 175000 475000                          result

 ==============================         end of parse
175000 475000                           result of immediate exec.

Example 2: Tacit Verbs

   sum=.+/
   lr (13!:16) _                        linear display of trace output

   s=. sum i.9
 -------------- 1 monad ------
 i.
 9                                      linear display of argument
 i.9                                    linear display of result

 -------------- 0 monad ------
 sum
 i.9

  ------------------------------        trace output is indented
  +/                                    one space for each level
  i.9                                   of function call

  36

  ==============================        end of trace at this level
 36                                     result of pending action

 -------------- 8 is ---------
 s
 =.
 36
 ==============================

   mean=: sum % #

 -------------- 5 trident ----
 sum
 %
 #
 sum % #

 -------------- 8 is ---------
 mean
 =:
 sum % #

 ==============================

   mean i.9

 -------------- 1 monad ------
 i.
 9
 i.9

 -------------- 0 monad ------
 mean
 i.9

  ------------------------------
  sum % #
  i.9

   ------------------------------
   +/
   i.9
   36

   ==============================
  4                                     result of mean

  ==============================
 4                                      result of pending monad

 ==============================

4                                       result of immediate exec.

Example 3: Explicit Verbs

agm defined below computes the arithmetic mean if the left argument is 0 and the geometric mean if it is 1.

   agm=: 4 : 'if. 0=x. do. (+/ % #)y. else. (*/ %:~ #)y.
                                                         end.'

   lr (13!:16) _

   0 agm 3 4 5 6

 -------------- 2 dyad -------
 0
 agm
 3 4 5 6

  ------------------------------
  0
  4 : 'if. 0=x. do. (+/ % #) y. else. (*/ %:~ #) y. end.'
  3 4 5 6

  ------------------------------
  0=x.                                  new line to be parsed

   -------------- 2 dyad -------
   0
   =
   0
   1

   ==============================       end of parse
   (+/%#)y.                             new line to be parsed

   -------------- 3 adverb -----
   +
   /
   +/

   -------------- 5 trident ----
   +/
   %
   #
   +/ % #

   -------------- 9 paren ------
   +/ % #

   -------------- 0 monad ------
   +/ % #
   3 4 5 6
   4.5                                  result of line (+/%#)y.

   ==============================
  4.5                                   result of pending dyad

  ==============================
 4.5                                    result of line 0 agm ...

 ==============================

4.5                                     result of immediate exec.

Example 4: Operators

Tracing an expression involving an operator can provide insight into the internal workings of that operator. Thus:

   sum=: +/

   lr (13!:16) _

   sum"1 i. 3 9

 -------------- 4 conj -------
 sum
 "
 1
 sum"1
 -------------- 1 monad ------
 i.
 3 9
 i.3 9
 -------------- 0 monad ------
 sum"1                                  apply sum to each
 i.3 9                                  vector of i.3 9
  ------------------------------
  +/
  i.9                                   cell 0
  36                                    result of cell 0
  ==============================
  +/
  9+i.9                                 cell 1
  117                                   result of cell 1
  ==============================
  +/
  18+i.9                                cell 2
  198                                   result of cell 2
  ==============================
 36 117 198                             overall result assembled
 ==============================         from the individual results
36 117 198
   sum\1 2 3                            sum prefixes
 -------------- 3 adverb -----
 sum
 \
 sum\
 -------------- 0 monad ------
 sum\
 1 2 3
  ------------------------------
  +/                                    The verb is applied to
  ,1                                    successively longer
  1                                     prefixes.
  ==============================
  +/
  1 2
  3
  ==============================
  +/
  1 2 3
  6
  ==============================
 1 3 6                                  overall result assembled
 ==============================         from individual results
1 3 6

Example 5: Errors

Tracing is quite effective at pinpointing the location of an error, because it shows the events leading up to the error.

   mean=: sum % #
   lr (13!:16) _
   mean i.9
 -------------- 1 monad ------
 i.
 9
 i.9
 -------------- 0 monad ------
 mean
 i.9
  ------------------------------
  sum % #
  i.9
 ==============================
|value error: sum                       the current verb is sum
|       mean i.9
   sum=: +/
 -------------- 3 adverb -----
 +
 /
 +/
 -------------- 8 is ---------
 sum
 =:
 +/
 ==============================
   mean 'asdf'
 -------------- 0 monad ------
 mean
 'asdf'
  ------------------------------
  sum % #
  'asdf'
   ------------------------------
   +/
   'asdf'
 ==============================
|domain error: sum                      the current verb is sum
|       mean'asdf'