force -- r7rs Definition procedure;
Procedure variants:
scheme:lazy -- (scheme lazy);scheme -- (scheme);(force promise)The
forceprocedure forces the value of apromisecreated bydelay,delay-force, ormake-promise. If no value has been computed for the promise, then a value is computed and returned. The value of the promise must be cached (or "memoized") so that if it is forced a second time, the previously computed value is returned. Consequently, a delayed expression is evaluated using the parameter values and exception handler of the call toforcewhich first requested its value. Ifpromiseis not a promise, it may be returned unchanged.(force (delay (+ 1 2))) ===> 3 (let ((p (delay (+ 1 2)))) (list (force p) (force p))) ===> (3 3) (define integers (letrec ((next (lambda (n) (delay (cons n (next (+ n 1))))))) (next 0))) (define head (lambda (stream) (car (force stream)))) (define tail (lambda (stream) (cdr (force stream)))) (head (tail (tail integers))) ===> 2The following example is a mechanical transformation of a lazy stream-filtering algorithm into Scheme. Each call to a constructor is wrapped in
delay, and each argument passed to a deconstructor is wrapped inforce. The use of(delay-force ...)instead of(delay (force ...))around the body of the procedure ensures that an ever-growing sequence of pending promises does not exhaust available storage, becauseforcewill in effect force such sequences iteratively.(define (stream-filter p? s) (delay-force (if (null? (force s)) (delay '()) (let ((h (car (force s))) (t (cdr (force s)))) (if (p? h) (delay (cons h (stream-filter p? t))) (stream-filter p? t)))))) (head (tail (tail (stream-filter odd? integers)))) ===> 5The following examples are not intended to illustrate good programming style, as
delay,force, anddelay-forceare mainly intended for programs written in the functional style. However, they do illustrate the property that only one value is computed for a promise, no matter how many times it is forced.(define count 0) (define p (delay (begin (set! count (+ count 1)) (if (> count x) count (force p))))) (define x 5) p ===> #promise (force p) ===> 6 p ===> #promise (begin (set! x 10) (force p)) ===> 6Various extensions to this semantics of
delay,forceanddelay-forceare supported in some implementations:
Calling
forceon an object that is not a promise may simply return the object.It may be the case that there is no means by which a promise can be operationally distinguished from its forced value. That is, expressions like the following may evaluate to either
#tor to#f, depending on the implementation:(eqv? (delay 1) 1) ===> #unspecified (pair? (delay (cons 1 2))) ===> #unspecified
- Implementations may implement "implicit forcing", where the value of a promise is forced by procedures that operate only on arguments of a certain type, like
cdrand*. However, procedures that operate uniformly on their arguments, likelist, must not force them.(+ (delay (* 3 7)) 13) ===> #unspecified (car (list (delay (* 3 7)) 13)) ===> #promise
The text herein was sourced and adapted as described in the "R7RS attribution of various text snippets" appendix.