From 4d5afda80e5e7a9ee23b713c654f8eb46b1a0327 Mon Sep 17 00:00:00 2001 From: Matthew Butterick Date: Sun, 23 Nov 2014 15:47:13 -0800 Subject: [PATCH] add compare; doc updates --- debug.rkt | 10 +++++++++- scribblings/cache.scrbl | 17 ++++++++++++++++- scribblings/debug.scrbl | 14 +++++++++++++- 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/debug.rkt b/debug.rkt index e8cb3ca..d666b15 100644 --- a/debug.rkt +++ b/debug.rkt @@ -30,4 +30,12 @@ (syntax-case stx () [(_ num expr ...) (let ([num (syntax->datum #'num)]) - (datum->syntax stx `(values ,@(map (λ(arg) `(time-repeat ,num ,arg)) (syntax->datum #'(expr ...))))))])) + (datum->syntax stx `(values ,@(map (λ(arg) `(time-repeat ,num ,arg)) (syntax->datum #'(expr ...))))))])) + + +(define-syntax (compare stx) + (syntax-case stx () + [(_ expr id id-alts ...) + (let ([expr (syntax->datum #'expr)] + [id (syntax->datum #'id)]) + (datum->syntax stx `(values ,expr ,@(map (λ(id-alt) `(let ([,id ,id-alt]) ,expr)) (syntax->datum #'(id-alts ...))))))])) diff --git a/scribblings/cache.scrbl b/scribblings/cache.scrbl index 95bb524..ae983a0 100644 --- a/scribblings/cache.scrbl +++ b/scribblings/cache.scrbl @@ -27,5 +27,20 @@ In the example below, notice that both invocations of @racketfont{slow-op} take (time (fast-op 42)) ] +Keep in mind that the cache is only available to external callers of the resulting function. So if @racket[_proc] calls itself recursively, these calls are @italic{not} accelerated by the cache. If that's the behavior you need, use @racket[define/caching] to create a new recursive function. + @defform[(define/caching (name arg ... . rest-arg) body ...)] -Like @racket[define], but automatically uses @racket[make-caching-proc] to define a caching version of the function. +Like @racket[define], but automatically uses @racket[make-caching-proc] to define a caching version of the function. If the function is recursive, the cache will be used for the recursive calls. + +In the example below, @racketfont{fib} is a recursive function. Notice that simply wrapping the function in @racket[make-caching-proc] doesn't work in this case, because @racketfont{fib}'s recursive calls to itself bypass the cache. But @racketfont{fib-fast} is rewritten to recur on the caching function, and the caching works as expected. + +@examples[#:eval my-eval +(define (fib x) + (if (< x 2) 1 (+ (fib (- x 1)) (fib (- x 2))))) +(define fibber (make-caching-proc fib)) +(define/caching (fib-fast x) + (if (< x 2) 1 (+ (fib-fast (- x 1)) (fib-fast (- x 2))))) +(time (fib 32)) +(time (fibber 32)) +(time (fib-fast 32)) +] \ No newline at end of file diff --git a/scribblings/debug.scrbl b/scribblings/debug.scrbl index f9d3a68..bb7751f 100644 --- a/scribblings/debug.scrbl +++ b/scribblings/debug.scrbl @@ -79,4 +79,16 @@ Apply @racket[time-repeat] to each @racket[_expr] individually. (time-repeat* 1000 (for/product ([i (in-range 1000)]) i) (for/sum ([i (in-range 1000)]) i)) -] \ No newline at end of file +] + +@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) +] +