diff options
-rw-r--r-- | doc/ref/srfi-modules.texi | 57 | ||||
-rw-r--r-- | module/srfi/srfi-45.scm | 21 | ||||
-rw-r--r-- | test-suite/tests/srfi-45.test | 43 |
3 files changed, 32 insertions, 89 deletions
diff --git a/doc/ref/srfi-modules.texi b/doc/ref/srfi-modules.texi index 347b3de1f..c99905c7d 100644 --- a/doc/ref/srfi-modules.texi +++ b/doc/ref/srfi-modules.texi @@ -3845,58 +3845,45 @@ words, no program that uses the R5RS definitions of delay and force will break if those definition are replaced by the SRFI-45 definitions of delay and force. -Guile compatibly extends SRFI-45 to support multiple values. It also -adds @code{promise?} to the list of exports. - -@deffn {Scheme Procedure} promise? obj -Return true if @var{obj} is an SRFI-45 promise, otherwise return false. -@end deffn - @deffn {Scheme Syntax} delay expression -Takes an expression and returns a promise which at some point in the -future may be asked (by the @code{force} procedure) to evaluate the -expression and deliver the resulting value(s). +Takes an expression of arbitrary type @var{a} and returns a promise of +type @code{(Promise @var{a})} which at some point in the future may be +asked (by the @code{force} procedure) to evaluate the expression and +deliver the resulting value. @end deffn @deffn {Scheme Syntax} lazy expression -Takes an expression (which must evaluate to a promise) and returns a -promise which at some point in the future may be asked (by the -@code{force} procedure) to evaluate the expression and deliver the -resulting promise. +Takes an expression of type @code{(Promise @var{a})} and returns a +promise of type @code{(Promise @var{a})} which at some point in the +future may be asked (by the @code{force} procedure) to evaluate the +expression and deliver the resulting promise. @end deffn -@deffn {Scheme Procedure} force promise -Takes a promise and returns the associated value(s) as follows: If -value(s) have been computed for the promise, these value(s) are -returned. Otherwise, the promise is first evaluated, then overwritten -by the obtained promise or value(s), and then force is again applied -(iteratively) to the promise. +@deffn {Scheme Procedure} force expression +Takes an argument of type @code{(Promise @var{a})} and returns a value +of type @var{a} as follows: If a value of type @var{a} has been computed +for the promise, this value is returned. Otherwise, the promise is +first evaluated, then overwritten by the obtained promise or value, and +then force is again applied (iteratively) to the promise. @end deffn -@deffn {Scheme Procedure} eager obj ... -Takes any number of argument(s) and returns a promise. As opposed to -@code{delay}, the argument(s) are evaluated eagerly. Semantically, -writing @code{(eager expression)} is equivalent to writing +@deffn {Scheme Procedure} eager expression +Takes an argument of type @var{a} and returns a value of type +@code{(Promise @var{a})}. As opposed to @code{delay}, the argument is +evaluated eagerly. Semantically, writing @code{(eager expression)} is +equivalent to writing @lisp (let ((value expression)) (delay value)). @end lisp However, the former is more efficient since it does not require -unnecessary creation and evaluation of thunks. For expressions that -return a single value, we also have the equivalence +unnecessary creation and evaluation of thunks. We also have the +equivalence @lisp (delay expression) = (lazy (eager expression)) @end lisp - -More generally, the following equivalence holds: - -@lisp -(delay expression) = (lazy (call-with-values - (lambda () expression) - eager)) -@end lisp @end deffn The following reduction rules may be helpful for reasoning about these @@ -3906,7 +3893,7 @@ usage semantics specified above: @lisp (force (delay expression)) -> expression (force (lazy expression)) -> (force expression) -(force (eager obj ...)) -> (values obj ...) +(force (eager value)) -> value @end lisp @subsubheading Correct usage diff --git a/module/srfi/srfi-45.scm b/module/srfi/srfi-45.scm index f865f912c..7b7fedd88 100644 --- a/module/srfi/srfi-45.scm +++ b/module/srfi/srfi-45.scm @@ -1,6 +1,6 @@ ;;; srfi-45.scm -- Primitives for Expressing Iterative Lazy Algorithms -;; Copyright (C) 2010, 2011, 2013 Free Software Foundation, Inc. +;; Copyright (C) 2010, 2011 Free Software Foundation, Inc. ;; Copyright (C) 2003 André van Tonder. All Rights Reserved. ;; Permission is hereby granted, free of charge, to any person @@ -25,8 +25,8 @@ ;;; Commentary: -;; This is the code of the reference implementation of SRFI-45, -;; modified to use SRFI-9 and to support multiple values. +;; This is the code of the reference implementation of SRFI-45, slightly +;; modified to use SRFI-9. ;; This module is documented in the Guile Reference Manual. @@ -36,9 +36,8 @@ #:export (delay lazy force - eager - promise?) - #:replace (delay force promise?) + eager) + #:replace (delay force) #:use-module (srfi srfi-9)) (cond-expand-provide (current-module) '(srfi-45)) @@ -53,18 +52,16 @@ (define-syntax-rule (lazy exp) (make-promise (make-value 'lazy (lambda () exp)))) -(define (eager . xs) - (make-promise (make-value 'eager xs))) +(define (eager x) + (make-promise (make-value 'eager x))) (define-syntax-rule (delay exp) - (lazy (call-with-values - (lambda () exp) - eager))) + (lazy (eager exp))) (define (force promise) (let ((content (promise-val promise))) (case (value-tag content) - ((eager) (apply values (value-proc content))) + ((eager) (value-proc content)) ((lazy) (let* ((promise* ((value-proc content))) (content (promise-val promise))) ; * (if (not (eqv? (value-tag content) 'eager)) ; * diff --git a/test-suite/tests/srfi-45.test b/test-suite/tests/srfi-45.test index cb3f7908f..573eea04a 100644 --- a/test-suite/tests/srfi-45.test +++ b/test-suite/tests/srfi-45.test @@ -1,7 +1,6 @@ ;;; -*- mode: scheme; coding: utf-8; -*- -;; Copyright (C) 2010, 2013 Free Software Foundation, Inc. -;; Copyright (C) 2003 André van Tonder. All Rights Reserved. +;; Copyright André van Tonder. All Rights Reserved. ;; ;; Permission is hereby granted, free of charge, to any person ;; obtaining a copy of this software and associated documentation @@ -259,43 +258,3 @@ ;; Commented out since it takes too long #; (test-equal 300000000 (force (times3 100000000))) ;==> bounded space - - -;====================================================================== -; Test promise? predicate (non-standard Guile extension) - -(pass-if "promise? predicate" - (promise? (delay 1))) - -;====================================================================== -; Test memoization of multiple values (non-standard Guile extension) - -(with-test-prefix "Multiple values (non-standard)" - - (let ((promise (delay (values 1 2 3)))) - (pass-if-equal "Multiple values delay" - '(1 2 3) - (call-with-values - (lambda () (force promise)) - list))) - - (let ((promise (eager 1 2 3))) - (pass-if-equal "Multiple values eager" - '(1 2 3) - (call-with-values - (lambda () (force promise)) - list))) - - (let ((promise (delay (values)))) - (pass-if-equal "Zero values delay" - '() - (call-with-values - (lambda () (force promise)) - list))) - - (let ((promise (eager))) - (pass-if-equal "Zero values eager" - '() - (call-with-values - (lambda () (force promise)) - list)))) |