{"size": 3599, "ext": "scrbl", "max_stars_repo_path": "sugar/scribblings/debug.scrbl", "max_stars_repo_name": "mbutterick/sugar", "max_stars_repo_stars_event_min_datetime": "2015-04-13T15:10:18.000Z", "max_stars_repo_stars_event_max_datetime": "2020-03-21T06:05:14.000Z", "max_issues_repo_path": "sugar/scribblings/debug.scrbl", "max_issues_repo_name": "mbutterick/sugar", "max_issues_repo_issues_event_min_datetime": "2015-04-13T15:38:56.000Z", "max_issues_repo_issues_event_max_datetime": "2020-02-16T20:00:54.000Z", "max_forks_repo_path": "sugar/scribblings/debug.scrbl", "max_forks_repo_name": "mbutterick/sugar", "max_forks_repo_forks_event_min_datetime": "2015-04-13T13:41:00.000Z", "max_forks_repo_forks_event_max_datetime": "2016-08-13T17:02:00.000Z"}
{"max_stars_count": 16, "max_issues_count": 18, "max_forks_count": 5, "avg_line_length": 34.2761904762, "max_line_length": 357, "alphanum_fraction": 0.7049180328}
#lang scribble/manual

@(require scribble/eval (for-label racket sugar))

@(define my-eval (make-base-eval))
@(my-eval `(require sugar))

@title{Debug}
@defmodule[#:multi (sugar/debug (submod sugar/debug safe))]

Debugging utilities.

@defform*[((report expr) (report expr maybe-name))]
Print the name and value of @racket[_expr] to @racket[current-error-port], but also return the evaluated result of @racket[_expr] as usual. This lets you see the value of an expression or variable at runtime without disrupting any of the surrounding code. Optionally, you can use @racket[_maybe-name] to change the name shown in @racket[current-error-port].

For instance, suppose you wanted to see how @racket[first-condition?] was being evaluted in this expression:

@racketblock[
(if (and (first-condition? x) (second-condition? x))
  (one-thing)
  (other-thing))]

You can wrap it in @racket[report] and find out:

@racketblock[
(if (and (report (first-condition? x)) (second-condition? x))
  (one-thing)
  (other-thing))]

This code will run the same way as before. But when it reaches @racket[first-condition?], you willl see in @racket[current-error-port]:

@racketerror{(first-condition? x) = #t}

You can also add standalone calls to @racket[report] as a debugging aid at points where the return value will be irrelevant, for instance:

@racketblock[
(report x x-before-function)
(if (and (report (first-condition? x)) (second-condition? x))
  (one-thing)
  (other-thing))]

@racketerror{x-before-function = 42
@(linebreak)(first-condition? x) = #t}

But be careful — in the example below, the result of the @racket[if] expression will be skipped in favor of the last expression, which will be the value of @racket[_x]:

@racketblock[
(if (and (report (first-condition? x)) (second-condition? x))
  (one-thing)
  (other-thing))
  (report x)]


@defform*[((report/line expr) (report/line expr maybe-name))]
Same as @racket[report], but also shows the line number of @racket[_expr].

@defform*[((report/file expr) (report/file expr maybe-name))]
Same as @racket[report], but also shows the line number and source-file name of @racket[_expr].

@deftogether[(
@defform[(report* expr ...)]
@defform[(report*/line expr ...)]
@defform[(report*/file expr ...)]
)]
Apply the relevant @racket[report] macro separately to each @racket[_expr] in the list.

@defform[(repeat num expr ...)]
Evaluate @racket[_expr] repeatedly — @racket[_num] times, in fact — and return the last value.

@examples[#:eval my-eval
(repeat 1000 
(for/sum ([i (in-range 1000)]) i))
]


@defform[(time-repeat num expr ...)]
Shorthand for using @racket[time] with @racket[repeat]. Repeat the whole list of expressions, print the total time, and return the last value.

@examples[#:eval my-eval
(time-repeat 1000 
(for/product ([i (in-range 1000)]) i)
(for/sum ([i (in-range 1000)]) i))
]

@defform[(time-repeat* num expr ...)]
Apply @racket[time-repeat] to each @racket[_expr] individually.

@examples[#:eval my-eval
(time-repeat* 1000 
(for/product ([i (in-range 1000)]) i)
(for/sum ([i (in-range 1000)]) i))
]

@defform[(compare expr id id-alt ...)]
Evaluate @racket[_expr] first using @racket[_id], and then again substituting @racket[_id-alt] in place of @racket[_id], and then again for every other @racket[_id-alt] in the list. This is useful for comparing the performance of multiple versions of a function.

@examples[#:eval my-eval
(define (fib x) 
  (if (< x 2) 1 (+ (fib (- x 1)) (fib (- x 2)))))
(define/caching (fib-fast x) 
  (if (< x 2) 1 (+ (fib-fast (- x 1)) (fib-fast (- x 2)))))
(compare (time (fib 34)) fib fib-fast)
]

