1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-20 19:50:24 +02:00

Revert "SRFI-45: Support multiple values; add promise? predicate."

This reverts commit 1d64b4edb9.
This commit is contained in:
Mark H Weaver 2013-03-26 21:16:26 -04:00
parent 59b0f9d763
commit 65ad02b96d
3 changed files with 32 additions and 89 deletions

View file

@ -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 break if those definition are replaced by the SRFI-45 definitions of
delay and force. 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 @deffn {Scheme Syntax} delay expression
Takes an expression and returns a promise which at some point in the Takes an expression of arbitrary type @var{a} and returns a promise of
future may be asked (by the @code{force} procedure) to evaluate the type @code{(Promise @var{a})} which at some point in the future may be
expression and deliver the resulting value(s). asked (by the @code{force} procedure) to evaluate the expression and
deliver the resulting value.
@end deffn @end deffn
@deffn {Scheme Syntax} lazy expression @deffn {Scheme Syntax} lazy expression
Takes an expression (which must evaluate to a promise) and returns a Takes an expression of type @code{(Promise @var{a})} and returns a
promise which at some point in the future may be asked (by the promise of type @code{(Promise @var{a})} which at some point in the
@code{force} procedure) to evaluate the expression and deliver the future may be asked (by the @code{force} procedure) to evaluate the
resulting promise. expression and deliver the resulting promise.
@end deffn @end deffn
@deffn {Scheme Procedure} force promise @deffn {Scheme Procedure} force expression
Takes a promise and returns the associated value(s) as follows: If Takes an argument of type @code{(Promise @var{a})} and returns a value
value(s) have been computed for the promise, these value(s) are of type @var{a} as follows: If a value of type @var{a} has been computed
returned. Otherwise, the promise is first evaluated, then overwritten for the promise, this value is returned. Otherwise, the promise is
by the obtained promise or value(s), and then force is again applied first evaluated, then overwritten by the obtained promise or value, and
(iteratively) to the promise. then force is again applied (iteratively) to the promise.
@end deffn @end deffn
@deffn {Scheme Procedure} eager obj ... @deffn {Scheme Procedure} eager expression
Takes any number of argument(s) and returns a promise. As opposed to Takes an argument of type @var{a} and returns a value of type
@code{delay}, the argument(s) are evaluated eagerly. Semantically, @code{(Promise @var{a})}. As opposed to @code{delay}, the argument is
writing @code{(eager expression)} is equivalent to writing evaluated eagerly. Semantically, writing @code{(eager expression)} is
equivalent to writing
@lisp @lisp
(let ((value expression)) (delay value)). (let ((value expression)) (delay value)).
@end lisp @end lisp
However, the former is more efficient since it does not require However, the former is more efficient since it does not require
unnecessary creation and evaluation of thunks. For expressions that unnecessary creation and evaluation of thunks. We also have the
return a single value, we also have the equivalence equivalence
@lisp @lisp
(delay expression) = (lazy (eager expression)) (delay expression) = (lazy (eager expression))
@end lisp @end lisp
More generally, the following equivalence holds:
@lisp
(delay expression) = (lazy (call-with-values
(lambda () expression)
eager))
@end lisp
@end deffn @end deffn
The following reduction rules may be helpful for reasoning about these The following reduction rules may be helpful for reasoning about these
@ -3906,7 +3893,7 @@ usage semantics specified above:
@lisp @lisp
(force (delay expression)) -> expression (force (delay expression)) -> expression
(force (lazy expression)) -> (force expression) (force (lazy expression)) -> (force expression)
(force (eager obj ...)) -> (values obj ...) (force (eager value)) -> value
@end lisp @end lisp
@subsubheading Correct usage @subsubheading Correct usage

View file

@ -1,6 +1,6 @@
;;; srfi-45.scm -- Primitives for Expressing Iterative Lazy Algorithms ;;; 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. ;; Copyright (C) 2003 André van Tonder. All Rights Reserved.
;; Permission is hereby granted, free of charge, to any person ;; Permission is hereby granted, free of charge, to any person
@ -25,8 +25,8 @@
;;; Commentary: ;;; Commentary:
;; This is the code of the reference implementation of SRFI-45, ;; This is the code of the reference implementation of SRFI-45, slightly
;; modified to use SRFI-9 and to support multiple values. ;; modified to use SRFI-9.
;; This module is documented in the Guile Reference Manual. ;; This module is documented in the Guile Reference Manual.
@ -36,9 +36,8 @@
#:export (delay #:export (delay
lazy lazy
force force
eager eager)
promise?) #:replace (delay force)
#:replace (delay force promise?)
#:use-module (srfi srfi-9)) #:use-module (srfi srfi-9))
(cond-expand-provide (current-module) '(srfi-45)) (cond-expand-provide (current-module) '(srfi-45))
@ -53,18 +52,16 @@
(define-syntax-rule (lazy exp) (define-syntax-rule (lazy exp)
(make-promise (make-value 'lazy (lambda () exp)))) (make-promise (make-value 'lazy (lambda () exp))))
(define (eager . xs) (define (eager x)
(make-promise (make-value 'eager xs))) (make-promise (make-value 'eager x)))
(define-syntax-rule (delay exp) (define-syntax-rule (delay exp)
(lazy (call-with-values (lazy (eager exp)))
(lambda () exp)
eager)))
(define (force promise) (define (force promise)
(let ((content (promise-val promise))) (let ((content (promise-val promise)))
(case (value-tag content) (case (value-tag content)
((eager) (apply values (value-proc content))) ((eager) (value-proc content))
((lazy) (let* ((promise* ((value-proc content))) ((lazy) (let* ((promise* ((value-proc content)))
(content (promise-val promise))) ; * (content (promise-val promise))) ; *
(if (not (eqv? (value-tag content) 'eager)) ; * (if (not (eqv? (value-tag content) 'eager)) ; *

View file

@ -1,7 +1,6 @@
;;; -*- mode: scheme; coding: utf-8; -*- ;;; -*- mode: scheme; coding: utf-8; -*-
;; Copyright (C) 2010, 2013 Free Software Foundation, Inc. ;; Copyright André van Tonder. All Rights Reserved.
;; Copyright (C) 2003 André van Tonder. All Rights Reserved.
;; ;;
;; Permission is hereby granted, free of charge, to any person ;; Permission is hereby granted, free of charge, to any person
;; obtaining a copy of this software and associated documentation ;; obtaining a copy of this software and associated documentation
@ -259,43 +258,3 @@
;; Commented out since it takes too long ;; Commented out since it takes too long
#; #;
(test-equal 300000000 (force (times3 100000000))) ;==> bounded space (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))))