srfi-45.scm 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  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. ;;; This document and translations of it may be copied and furnished to
  5. ;;; others, and derivative works that comment on or otherwise explain it
  6. ;;; or assist in its implementation may be prepared, copied, published and
  7. ;;; distributed, in whole or in part, without restriction of any kind,
  8. ;;; provided that the above copyright notice and this paragraph are
  9. ;;; included on all such copies and derivative works. However, this
  10. ;;; document itself may not be modified in any way, such as by removing
  11. ;;; the copyright notice or references to the Scheme Request For
  12. ;;; Implementation process or editors, except as needed for the purpose of
  13. ;;; developing SRFIs in which case the procedures for copyrights defined
  14. ;;; in the SRFI process must be followed, or as required to translate it
  15. ;;; into languages other than English.
  16. ;;; The limited permissions granted above are perpetual and will not be
  17. ;;; revoked by the authors or their successors or assigns.
  18. ;;; This document and the information contained herein is provided on an
  19. ;;; "AS IS" basis and THE AUTHOR AND THE SRFI EDITORS DISCLAIM ALL
  20. ;;; WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY
  21. ;;; WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY
  22. ;;; RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
  23. ;;; PARTICULAR PURPOSE.
  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.