| 1 | @c -*-texinfo-*- |
| 2 | @c This is part of the GNU Guile Reference Manual. |
| 3 | @c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2006 |
| 4 | @c Free Software Foundation, Inc. |
| 5 | @c See the file guile.texi for copying conditions. |
| 6 | |
| 7 | @page |
| 8 | @node Tracing |
| 9 | @section Tracing |
| 10 | |
| 11 | The @code{(ice-9 debug)} module implements tracing of procedure |
| 12 | applications. When a procedure is @dfn{traced}, it means that every |
| 13 | call to that procedure is reported to the user during a program run. |
| 14 | The idea is that you can mark a collection of procedures for tracing, |
| 15 | and Guile will subsequently print out a line of the form |
| 16 | |
| 17 | @lisp |
| 18 | | | [@var{procedure} @var{args} @dots{}] |
| 19 | @end lisp |
| 20 | |
| 21 | whenever a marked procedure is about to be applied to its arguments. |
| 22 | This can help a programmer determine whether a function is being called |
| 23 | at the wrong time or with the wrong set of arguments. |
| 24 | |
| 25 | In addition, the indentation of the output is useful for demonstrating |
| 26 | how the traced applications are or are not tail recursive with respect |
| 27 | to each other. Thus, a trace of a non-tail recursive factorial |
| 28 | implementation looks like this: |
| 29 | |
| 30 | @lisp |
| 31 | [fact1 4] |
| 32 | | [fact1 3] |
| 33 | | | [fact1 2] |
| 34 | | | | [fact1 1] |
| 35 | | | | | [fact1 0] |
| 36 | | | | | 1 |
| 37 | | | | 1 |
| 38 | | | 2 |
| 39 | | 6 |
| 40 | 24 |
| 41 | @end lisp |
| 42 | |
| 43 | While a typical tail recursive implementation would look more like this: |
| 44 | |
| 45 | @lisp |
| 46 | [fact2 4] |
| 47 | [facti 1 4] |
| 48 | [facti 4 3] |
| 49 | [facti 12 2] |
| 50 | [facti 24 1] |
| 51 | [facti 24 0] |
| 52 | 24 |
| 53 | @end lisp |
| 54 | |
| 55 | @deffn {Scheme Procedure} trace procedure |
| 56 | Enable tracing for @code{procedure}. While a program is being run, |
| 57 | Guile will print a brief report at each call to a traced procedure, |
| 58 | advising the user which procedure was called and the arguments that were |
| 59 | passed to it. |
| 60 | @end deffn |
| 61 | |
| 62 | @deffn {Scheme Procedure} untrace procedure |
| 63 | Disable tracing for @code{procedure}. |
| 64 | @end deffn |
| 65 | |
| 66 | Here is another example: |
| 67 | |
| 68 | @lisp |
| 69 | (define (rev ls) |
| 70 | (if (null? ls) |
| 71 | '() |
| 72 | (append (rev (cdr ls)) |
| 73 | (cons (car ls) '())))) @result{} rev |
| 74 | |
| 75 | (trace rev) @result{} (rev) |
| 76 | |
| 77 | (rev '(a b c d e)) |
| 78 | @result{} [rev (a b c d e)] |
| 79 | | [rev (b c d e)] |
| 80 | | | [rev (c d e)] |
| 81 | | | | [rev (d e)] |
| 82 | | | | | [rev (e)] |
| 83 | | | | | | [rev ()] |
| 84 | | | | | | () |
| 85 | | | | | (e) |
| 86 | | | | (e d) |
| 87 | | | (e d c) |
| 88 | | (e d c b) |
| 89 | (e d c b a) |
| 90 | (e d c b a) |
| 91 | @end lisp |
| 92 | |
| 93 | Note the way Guile indents the output, illustrating the depth of |
| 94 | execution at each procedure call. This can be used to demonstrate, for |
| 95 | example, that Guile implements self-tail-recursion properly: |
| 96 | |
| 97 | @lisp |
| 98 | (define (rev ls sl) |
| 99 | (if (null? ls) |
| 100 | sl |
| 101 | (rev (cdr ls) |
| 102 | (cons (car ls) sl)))) @result{} rev |
| 103 | |
| 104 | (trace rev) @result{} (rev) |
| 105 | |
| 106 | (rev '(a b c d e) '()) |
| 107 | @result{} [rev (a b c d e) ()] |
| 108 | [rev (b c d e) (a)] |
| 109 | [rev (c d e) (b a)] |
| 110 | [rev (d e) (c b a)] |
| 111 | [rev (e) (d c b a)] |
| 112 | [rev () (e d c b a)] |
| 113 | (e d c b a) |
| 114 | (e d c b a) |
| 115 | @end lisp |
| 116 | |
| 117 | Since the tail call is effectively optimized to a @code{goto} statement, |
| 118 | there is no need for Guile to create a new stack frame for each |
| 119 | iteration. Tracing reveals this optimization in operation. |
| 120 | |
| 121 | |
| 122 | @c Local Variables: |
| 123 | @c TeX-master: "guile.texi" |
| 124 | @c End: |