srfi-45.scm 2.9 KB

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