srfi-45.scm 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. ;;; SRFI 45, which this code is part of, bears the following
  2. ;;; copyright/license notice:
  3. ;;; Copyright (C) André van Tonder (2003). All Rights Reserved.
  4. ;;;
  5. ;;; Permission is hereby granted, free of charge, to any person
  6. ;;; obtaining a copy of this software and associated documentation
  7. ;;; files (the "Software"), to deal in the Software without
  8. ;;; restriction, including without limitation the rights to use, copy,
  9. ;;; modify, merge, publish, distribute, sublicense, and/or sell copies
  10. ;;; of the Software, and to permit persons to whom the Software is
  11. ;;; furnished to do so, subject to the following conditions:
  12. ;;;
  13. ;;; The above copyright notice and this permission notice shall be
  14. ;;; included in all copies or substantial portions of the Software.
  15. ;;;
  16. ;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  17. ;;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  18. ;;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  19. ;;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  20. ;;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  21. ;;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. ;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  23. ;;; DEALINGS IN THE SOFTWARE.
  24. (define-record-type promise :promise
  25. (make-promise pair)
  26. promise?
  27. ;; This pair has as a car either 'EAGER (in which case the cdr is
  28. ;; the value) or 'LAZY (in which case the cdr is a thunk).
  29. (pair promise-ref set-promise!))
  30. (define-record-discloser :promise
  31. (lambda (r)
  32. (case (car (promise-ref r))
  33. ((eager)
  34. (list 'promise 'eager (cdr (promise-ref r))))
  35. ((lazy)
  36. (list 'promise 'lazy)))))
  37. ;;;=========================================================================
  38. ;;; Primitives for lazy evaluation:
  39. (define-syntax lazy
  40. (syntax-rules ()
  41. ((lazy exp)
  42. (make-promise (cons 'lazy (lambda () exp))))))
  43. (define (eager x)
  44. (make-promise (cons 'eager x)))
  45. (define-syntax delay
  46. (syntax-rules ()
  47. ((delay exp) (lazy (eager exp)))))
  48. (define (force promise)
  49. (let ((content (promise-ref promise)))
  50. (case (car content)
  51. ((eager) (cdr content))
  52. ((lazy) (let* ((promise* ((cdr content)))
  53. (content (promise-ref promise))) ; *
  54. (if (not (eqv? (car content) 'eager)) ; *
  55. (begin (set-car! content (car (promise-ref promise*)))
  56. (set-cdr! content (cdr (promise-ref promise*)))
  57. (set-promise! promise* content)))
  58. (force promise))))))
  59. ; (*) These two lines re-fetch and check the original promise in case
  60. ; the first line of the let* caused it to be forced. For an example
  61. ; where this happens, see reentrancy test 3 below.