diff --git a/CHANGELOG.md b/CHANGELOG.md index e8c5bd96..7be9a0b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ Features Bug Fixes +- Improved `(scheme lazy)` to allow `force` and `make-promise` to accept an argument of any type. Improved representation of promises to more precisely differentiate them from other objects. - Add type checking to record type accessor functions. We now raise an error if the passed object is of the wrong record type. - Fix issues with expanding `cond-expand` expressions in libraries. Previously there would be issues with the expansion if the code needed to be within the context of a `begin`. diff --git a/scheme/lazy.sld b/scheme/lazy.sld index f47430a1..bd144387 100644 --- a/scheme/lazy.sld +++ b/scheme/lazy.sld @@ -17,9 +17,19 @@ ) (begin + ;; promise + ;; ( tag value/obj ) + + (define *promise-tag* '(promise)) + (define (promise? obj) + (and (pair? obj) + (eq? *promise-tag* (car obj)))) + (define force - (lambda (object) - (object))) + (lambda (obj) + (if (promise? obj) + ((cdr obj)) + obj))) (define-syntax delay (er-macro-transformer @@ -32,20 +42,23 @@ `(make-promise (lambda () ,(cadr expr)))))) (define make-promise - (lambda (proc) - (let ((result-ready? #f) - (result #f)) - (lambda () - (if result-ready? - result - (let ((x (proc))) - (if result-ready? + (lambda (obj) + (if (promise? obj) + obj + (let ((result-ready? #f) + (result #f)) + (cons + *promise-tag* + (lambda () + (if result-ready? result - (begin (set! result x) - (set! result-ready? #t) - result)))))))) + (let ((x (if (procedure? obj) + (obj) + obj))) + (if result-ready? + result + (begin (set! result x) + (set! result-ready? #t) + result)))))))))) - ;; Not a very satisfying implementation, but would need to change - ;; how promises are stored to do better - (define promise? procedure?) ))