;;; Copyright (C) 2025 Free Software Foundation, Inc. ;;; ;;; This library is free software: you can redistribute it and/or modify ;;; it under the terms of the GNU Lesser General Public License as ;;; published by the Free Software Foundation, either version 3 of the ;;; License, or (at your option) any later version. ;;; ;;; This library is distributed in the hope that it will be useful, but ;;; WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;; Lesser General Public License for more details. ;;; ;;; You should have received a copy of the GNU Lesser General Public ;;; License along with this program. If not, see ;;; . ;;; Commentary: ;;; ;;; ;;; Code: (define-module (ice-9 promises) #:use-module (srfi srfi-9) #:use-module (ice-9 threads) ;; FIXME: #:export instead of #:replace when deprecated code removed #:replace (make-promise force delay promise?)) (define-record-type (%make-promise computed? data lock) %promise? (computed? promise-computed? set-promise-computed?!) (data promise-data set-promise-data!) (lock promise-lock)) (define (make-promise thunk) "Create a new promise object. @code{make-promise} is a procedural form of @code{delay}. These two expressions are equivalent: @lisp (delay @var{exp}) (make-promise (lambda () @var{exp})) @end lisp" (%make-promise #f thunk (make-recursive-mutex))) (define-syntax-rule (delay exp) (make-promise (lambda () exp))) (define (force promise) "If @var{promise} has not been computed yet, compute and return @var{promise}, otherwise just return the previously computed value." (with-mutex (promise-lock promise) (if (promise-computed? promise) (promise-data promise) (let* ((thunk (promise-data promise)) (ans (thunk))) (if (promise-computed? promise) (promise-data promise) (begin (set-promise-computed?! promise #t) (set-promise-data! promise ans) ans)))))) (define (promise? x) "Return true if @var{obj} is a promise, i.e. a delayed computation (@pxref{Delayed evaluation,,,r5rs.info,The Revised^5 Report on Scheme})." (%promise? x))