The following examples show what tracing is and the kind of output that it generates. In the first example, we define a recursive function for reversing a list, then watch the effect of the recursive calls by tracing each call and return value.
guile> (define (rev ls) (if (null? ls) ls (append (rev (cdr ls)) (list (car ls))))) guile> (use-modules (ice-9 debugging traps) (ice-9 debugging trace)) guile> (define t1 (make <procedure-trap> #:procedure rev #:behaviour (list trace-trap trace-at-exit))) guile> (install-trap t1) guile> (rev '(a b c)) | 2: [rev (a b c)] | 3: [rev (b c)] | 4: [rev (c)] | 5: [rev ()] | 5: =>() | 4: =>(c) | 3: =>(c b) | 2: =>(c b a) (c b a)
The number before the colon in this output (which follows (ice-9
debugging trace)
's default output format) is the number of real frames
on the stack. The fact that this number increases for each recursive
call confirms that the implementation above of rev
is not
tail-recursive.
In the next example, we probe the internal workings of
rev
in more detail by using the trace-until-exit
behaviour.
guile> (uninstall-trap t1) guile> (define t2 (make <procedure-trap> #:procedure rev #:behaviour (list trace-trap trace-until-exit))) guile> (install-trap t2) guile> (rev '(a b)) | 2: [rev (a b)] | 2: (if (null? ls) ls (append (rev (cdr ls)) (list (car ls)))) | 3: (null? ls) | 3: [null? (a b)] | 3: =>#f | 2: (append (rev (cdr ls)) (list (car ls))) | 3: (rev (cdr ls)) | 4: (cdr ls) | 4: [cdr (a b)] | 4: =>(b) | 3: [rev (b)] | 3: (if (null? ls) ls (append (rev (cdr ls)) (list (car ls)))) | 4: (null? ls) | 4: [null? (b)] | 4: =>#f | 3: (append (rev (cdr ls)) (list (car ls))) | 4: (rev (cdr ls)) | 5: (cdr ls) | 5: [cdr (b)] | 5: =>() | 4: [rev ()] | 4: (if (null? ls) ls (append (rev (cdr ls)) (list (car ls)))) | 5: (null? ls) | 5: [null? ()] | 5: =>#t | 4: (list (car ls)) | 5: (car ls) | 5: [car (b)] | 5: =>b | 4: [list b] | 4: =>(b) | 3: [append () (b)] | 3: =>(b) | 3: (list (car ls)) | 4: (car ls) | 4: [car (a b)] | 4: =>a | 3: [list a] | 3: =>(a) | 2: [append (b) (a)] | 2: =>(b a) (b a)
The output in this case shows every step that the evaluator performs
in evaluating (rev '(a b))
.