For Development HEAD DRAFTSearch (procedure/syntax/module):

11.30 srfi.154 - First-class dynamic extents

Module: srfi.154

This module provides a convenient way to reify the dynamic environment. A continuation captured by call/cc includes the dynamic environment, as well as the control flow. Sometimes you only want the dynamic environment part. A dynamic extent is a reified dynamic environment.

Let’s see an example. You want a procedure that prints out a message to the error port, so you wrote this print-error:

(define print-error
  (lambda (msg) (display msg (current-error-port))))

However, if print-error is called while the current error port is altered, it is affected. It is supposed to be so, that’s the point of current-error-port.

(call-with-output-string
  (^p (with-error-to-port p (^[] (print-error "abc\n")))))
 ⇒ "abc\n"

If you do want print-error to use the error port at the time it is defined, you have to extract the dynamic value at the moment.

(define print-error
  (let1 eport (current-error-port)
    (lambda (msg) (display msg eport))))

This would be quickly cumbersome when you need to capture multiple dynamic values, or the original print-error is called indirectly and you can’t modify it the way shown above.

Using dynamic-lambda addresses this issue. It not only captures the lexical environment, but also the dynamic environment when it is evaluated. So the current-error-port in its body returns the current error port at the time of print-error being defined, not when it is called:

(define print-error
  (dynamic-lambda (msg) (display msg (current-error-port))))
Function: current-dynamic-extent

[SRFI-154]{srfi.154} Returns a dynamic-extent object that reifies the current dynamic environment.

Function: dynamic-extent? obj

[SRFI-154]{srfi.154} Returns #t iff obj is a dynamic-extent object.

Function: with-dynamic-extent dynext thunk

[SRFI-154]{srfi.154} Calls the thunk in the dynamic extent dynext, and returns the values yielded by thunk.

Macro: dynamic-lambda formals body …

[SRFI-154]{srfi.154} Like lambda, but this not only captures the lexical environment, but also the dynamic environment. Yields a procedure.

Note: Since dynamic-lambda needs to swap the dynamic environment after executing body, the last expression of body isn’t called in the tail context even if the procedure created by dynamic-lambda is called in tail context.



For Development HEAD DRAFTSearch (procedure/syntax/module):
DRAFT