This commit is contained in:
Yuichi Nishiwaki 2016-06-03 01:44:03 +09:00
parent d9f4380ae8
commit 365ccc7a51
1 changed files with 23 additions and 42 deletions

View File

@ -1,60 +1,41 @@
;;; Appendix A. Standard Libraries Lazy ;;; Appendix A. Standard Libraries Lazy
(define-library (scheme lazy) (define-library (scheme lazy)
(import (scheme base) (import (scheme base))
(picrin macro))
;; type 'a <promise> = cached of 'a | chained of 'a promise | pending of () -> 'a promise
(define-record-type <promise> (define-record-type <promise>
(make-promise% done value) (promise state value)
promise?% promise?
(done promise-done?% set-promise-done!%) (state promise-state set-promise-state!)
(value promise-value% set-promise-value!%)) (value promise-value set-promise-value!))
(define (box x) (list x)) (define (make-promise obj)
(define box? list?) (if (promise? obj)
(define unbox car) obj
(define set-box! set-car!) (promise 'cached obj)))
(define (promise? x)
(promise?% (unbox x)))
(define (promise-done? x)
(promise-done?% (unbox x)))
(define (set-promise-done! boxed x)
(set-promise-done!% (unbox boxed) x))
(define (promise-value x)
(promise-value% (unbox x)))
(define (set-promise-value! boxed x)
(set-promise-value!% (unbox boxed) x))
(define (make-promise%% done value)
(box (make-promise% done value)))
(define-syntax delay-force (define-syntax delay-force
(syntax-rules () (syntax-rules ()
((_ expr) ((_ expr)
(make-promise%% #f (lambda () expr))))) (promise (string->symbol "pending") (lambda () expr)))))
(define-syntax delay (define-syntax delay
(syntax-rules () (syntax-rules ()
((_ expr) ((_ expr)
(delay-force (make-promise%% #t expr))))) (delay-force (make-promise expr)))))
(define (force promise) (define (force p)
(if (promise-done? promise) (let ((v (promise-value p)))
(promise-value promise) (case (promise-state p)
(let ((new-promise ((promise-value promise)))) ((cached) v)
(if (promise-done? promise) ((chained) (force v))
(promise-value promise) ((pending) (let ((q (v)))
(begin (when (eq? 'pending (promise-state p))
(set-promise-done! promise (promise-done? new-promise)) (set-promise-state! p 'chained)
(set-promise-value! promise (promise-value new-promise)) (set-promise-value! p q))
(set-box! new-promise (unbox promise)) (force p))))))
(force promise))))))
(define (make-promise obj)
(if (and (box? obj) (promise? obj))
obj
(make-promise%% #t obj)))
(export delay-force (export delay-force
delay delay