7.7

1 Structured Debugging

The debug collection provides debugging utilities that automatically trace flow into and out of debugged portions of the program and format debugging output to reflect that call stack. The collection includes the languages debug/racket and debug/mischief that automatically add debugging to primitive forms. The no-debug collection includes variants of everything in debug that execute identically but disable debugging output, so turning debugging on or off simply means replacing (require debug) with (require no-debug) or vice-versa.

Examples:
> (define/debug (sum xs)
    (debug* cond
      [(empty? (rest xs)) (first xs)]
      [else (debug + (first xs) (sum (rest xs)))]))
> (debug sum (build-list 3 add1))

#;>> application: (sum (build-list 3 add1)) [eval:2.0]

#; >> expression: sum [eval:2.0]

#;  ! Result: '#<procedure:sum>

#; << expression: sum [eval:2.0]

#; >> expression: (build-list 3 add1) [eval:2.0]

#;  ! Result: '(1 2 3)

#; << expression: (build-list 3 add1) [eval:2.0]

#; >> function: sum [eval:1.0]

#;  ! Argument xs: '(1 2 3)

#;  >> expression:

#;  >>  (cond

#;  >>   ((empty? (rest xs)) (first xs))

#;  >>   (else (debug + (first xs) (sum (rest xs)))))

#;  >>  [eval:1.0]

#;   >> application: (+ (first xs) (sum (rest xs))) [eval:1.0]

#;    >> expression: + [eval:1.0]

#;     ! Result: '#<procedure:+>

#;    << expression: + [eval:1.0]

#;    >> expression: (first xs) [eval:1.0]

#;     ! Result: 1

#;    << expression: (first xs) [eval:1.0]

#;    >> expression: (sum (rest xs)) [eval:1.0]

#;     >> function: sum [eval:1.0]

#;      ! Argument xs: '(2 3)

#;      >> expression:

#;      >>  (cond

#;      >>   ((empty? (rest xs)) (first xs))

#;      >>   (else (debug + (first xs) (sum (rest xs)))))

#;      >>  [eval:1.0]

#;       >> application: (+ (first xs) (sum (rest xs))) [eval:1.0]

#;        >> expression: + [eval:1.0]

#;         ! Result: '#<procedure:+>

#;        << expression: + [eval:1.0]

#;        >> expression: (first xs) [eval:1.0]

#;         ! Result: 2

#;        << expression: (first xs) [eval:1.0]

#;        >> expression: (sum (rest xs)) [eval:1.0]

#;         >> function: sum [eval:1.0]

#;          ! Argument xs: '(3)

#;          >> expression:

#;          >>  (cond

#;          >>   ((empty? (rest xs)) (first xs))

#;          >>   (else (debug + (first xs) (sum (rest xs)))))

#;          >>  [eval:1.0]

#;           ! Result: 3

#;          << expression:

#;          <<  (cond

#;          <<   ((empty? (rest xs)) (first xs))

#;          <<   (else (debug + (first xs) (sum (rest xs)))))

#;          <<  [eval:1.0]

#;          ! Result: 3

#;         << function: sum [eval:1.0]

#;         ! Result: 3

#;        << expression: (sum (rest xs)) [eval:1.0]

#;        ! Result: 5

#;       << application: (+ (first xs) (sum (rest xs))) [eval:1.0]

#;       ! Result: 5

#;      << expression:

#;      <<  (cond

#;      <<   ((empty? (rest xs)) (first xs))

#;      <<   (else (debug + (first xs) (sum (rest xs)))))

#;      <<  [eval:1.0]

#;      ! Result: 5

#;     << function: sum [eval:1.0]

#;     ! Result: 5

#;    << expression: (sum (rest xs)) [eval:1.0]

#;    ! Result: 6

#;   << application: (+ (first xs) (sum (rest xs))) [eval:1.0]

#;   ! Result: 6

#;  << expression:

#;  <<  (cond

#;  <<   ((empty? (rest xs)) (first xs))

#;  <<   (else (debug + (first xs) (sum (rest xs)))))

#;  <<  [eval:1.0]

#;  ! Result: 6

#; << function: sum [eval:1.0]

#; ! Result: 6

#;<< application: (sum (build-list 3 add1)) [eval:2.0]

6

> (debug sum (build-list 0 add1))

#;>> application: (sum (build-list 0 add1)) [eval:3.0]

#; >> expression: sum [eval:3.0]

#;  ! Result: '#<procedure:sum>

#; << expression: sum [eval:3.0]

#; >> expression: (build-list 0 add1) [eval:3.0]

#;  ! Result: '()

#; << expression: (build-list 0 add1) [eval:3.0]

#; >> function: sum [eval:1.0]

#;  ! Argument xs: '()

#;  >> expression:

#;  >>  (cond

#;  >>   ((empty? (rest xs)) (first xs))

#;  >>   (else (debug + (first xs) (sum (rest xs)))))

#;  >>  [eval:1.0]

#;   ! Exception:

#;   !  (raise

#;   !   (exn:fail:contract

#;   !    "rest: contract violation\n  expected: (and/c list? (not/c empty?))\n  given: '()"

#;   !    '#<continuation-mark-set>))

#;  << expression:

#;  <<  (cond

#;  <<   ((empty? (rest xs)) (first xs))

#;  <<   (else (debug + (first xs) (sum (rest xs)))))

#;  <<  [eval:1.0]

#;  ! Exception:

#;  !  (raise

#;  !   (exn:fail:contract

#;  !    "rest: contract violation\n  expected: (and/c list? (not/c empty?))\n  given: '()"

#;  !    '#<continuation-mark-set>))

#; << function: sum [eval:1.0]

#; ! Exception:

#; !  (raise

#; !   (exn:fail:contract

#; !    "rest: contract violation\n  expected: (and/c list? (not/c empty?))\n  given: '()"

#; !    '#<continuation-mark-set>))

#;<< application: (sum (build-list 0 add1)) [eval:3.0]

rest: contract violation

  expected: (and/c list? (not/c empty?))

  given: '()