Multiple values Eli Barzilay 16 Oct 2006 01:08 UTC
FWIW, here is an implementation of lazy/eager/delay/force that works with multiple values. Additional notes: * Works on PLT, but this is mostly a technicality. One thing is that some diverging tests fail on PLT v352, but everything seems to work fine on v352.7 (we think that it's because Matthew did some work on optimizing `call-with-values' recently). * Requires `eager' to be a syntax too, so it can handle multiple values. * Clarifies the relationship between plain `delay' and `lazy' (close to the Dybvig implementation that is used in MzScheme). The latter is similar, but injects an extra level of reference, to short-circuit force chains. (define-struct promise (p)) (define-syntax lazy (syntax-rules () [(lazy exp) (box (make-promise (lambda () exp)))])) (define-syntax eager (syntax-rules () [(eager exp) (box (make-promise (call-with-values (lambda () exp) list)))])) (define-syntax delay (syntax-rules () [(delay exp) (lazy (eager exp))])) (define (force boxed) (let* ([promise (unbox boxed)] [content (promise-p promise)]) (if (procedure? content) (let* ([boxed* (content)] [promise (unbox boxed)]) ; * (when (procedure? (promise-p promise)) ; * (set-promise-p! promise (promise-p (unbox boxed*))) (set-box! boxed* promise)) (force boxed)) (apply values content)))) ;; (*) These two lines re-fetch and check the original promise in case ;; the first line of the let* caused it to be forced. For an example ;; where this happens, see reentrancy test 3 below. -- ((lambda (x) (x x)) (lambda (x) (x x))) Eli Barzilay: http://www.barzilay.org/ Maze is Life!