This SRFI is currently in draft status. Here is an explanation of each status that a SRFI can hold. To provide input on this SRFI, please send email to
email@example.com. To subscribe to the list, follow these instructions. You can access previous messages via the mailing list archive.
parameterizedeal with the dynamic extent indirectly. This SRFI reifies the dynamic extent into a first-class value together with a well-defined procedural interface and a syntax to create procedures that remember not only their environment at creation time but also their dynamic extent, which includes their dynamic environment.
closed-lambdamight be in need of a better name.
While the Scheme language is rich enough to reify the concept of the dynamic extent of a procedure — the sample implementation accompanying this SRFI is a proof of this fact — there is no standard for how such a reification is exposed to the user. It is the purpose of this SRFI to remedy this. In particular, Scheme systems may provide faster implementations than the portable sample implementation of this SRFI.
To give an example why explicit handling of dynamic extents can become necessary, let us consider the following two definitions:
(define (safe-sqrt error-handler) (lambda (x) (when (negative? x) (error-handler "negative argument")) (sqrt x))) (define (error-handler msg) (display msg (current-error-port)) (newline (current-error-port)) 'error) (define my-safe-sqrt (safe-sqrt error-handler))
(my-safe-sqrt -1) is executed, an error
message is printed on the current error port of the call
my-safe-sqrt. It may, however, have been the
intention of the user that the message is printed to whatever
error port was current when the
error-handler was defined. Using the
syntax of this SRFI, this can be achieved by changing the
(define error-handler (closed-lambda (msg) (display msg (current-error-port)) (newline (current-error-port)) 'error))
The same goes not only for error handlers, but for any other
type of callback procedure where it often makes sense to
reinstate the dynamic extent of the definition of the
callback for the dynamic extent of the call to the
callback, e.g. to define the callback
closed-lambda as opposed to using a
In case the error handler from the example above wants to call back on a provided continuation, we have to be a bit more careful so that the continuation is called in the expected dynamic extent:
(define (safe-sqrt error-handler) (lambda (x) (when (negative? x) (error-handler "negative argument" exit)) (sqrt x))) (define error-handler (let ((dynamic-extent (current-dynamic-extent))) (lambda (msg exit) (with-dynamic-extent dynamic-extent (lambda () (display msg (current-error-port)) (newline (current-error-port)))) (exit 'error)))) (define my-safe-sqrt (safe-sqrt error-handler))
Note that the example of the error handler above is meant as a
minimal example in order to demonstrate the capabalities of this
library. It is not an example that cannot easily be rewritten
in Scheme code not making use of this SRFI, e.g. by
taking a snapshot of the value
current-error-port in form of a lexical
variable. However note that in general more than one parameter
object may be accessed in the dynamic extent of the body of
closed-lambda or that they are not necessarily
known. In the presence
39- parameter objects, which are mutable, the technique of
taking a snapshot of the current value won't work. Finally, the
dynamic extent can be much more complicated than just about
parameter objects. For example, there could be global state that
is setup and restored by
dynamic-wind. In all
these cases, this SRFI provides the cleanest solution.
Another use case
155, which provides a specification and an implementation of
promises such that lazy algorithms using them work well in the presence
call-with-current-continuation and dynamically
Throughout, we reuse the term dynamic extent for a reified
dynamic extent. In this sense, the
thunk of a call to
sets up the dynamic extent of the call
after thunk restores the dynamic
extent of the call to
Dynamic extents form a type not necessarily disjoint from other Scheme types.
#t if its argument is a dynamic extent,
#f otherwise. Note that dynamic extents are not
necessarily disjoint from other Scheme types such as procedures.
current-dynamic-extent procedure returns
the current dynamic extent by capturing the dynamic extent
of the call to
can be reinstated by the
(with-dynamic-extent dynamic-extent thunk)
with-dynamic-extent procedure calls
thunk and returns the values yielded
thunk. The call
thunk happens in the dynamic extent
captured by the
(closed-lambda <formals> <body>)
closed-lambda expression is equivalent
lambda expression except that not only the
environment but also the dynamic extent in effect when the
closed-lambda expression was evaluated is
In other words, the expression
<formals> <body>) closes also over the
The sample implementation is provided
as an R7RS-library. It should be easily adaptable to any Scheme
implementation as long as that implementation has a concept of
call-with-current-continuation, and has a
macro facility (for implementing
The sample implementation includes a special algorithm for use with Chibi Scheme. This serves as a demonstration how efficient implementations of this specification can be provided by Scheme implementers.
Thanks go to the SRFI editor for keeping the SRFI process alive and running..
Copyright (C) Marc Nieper-Wißkirchen (2017). All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.