#lang scribble/doc @(require scribble/struct scribble/scheme "mz.ss") @(define (cont n) (make-element variable-color (list "C" (make-element 'subscript (list (format "~a" n)))))) @title[#:tag "contmarks"]{Continuation Marks} See @secref["mark-model"] and @secref["prompt-model"] for general information about continuation marks. The list of continuation marks for a key @scheme[_k] and a continuation @scheme[_C] that extends @cont[0] is defined as follows: @itemize[ @item{If @scheme[_C] is an empty continuation, then the mark list is @scheme[null].} @item{If @scheme[_C]'s first frame contains a mark @scheme[_m] for @scheme[_k], then the mark list for @scheme[_C] is @scheme[(cons _m _lst)], where @scheme[_lst] is the mark list for @scheme[_k] in @cont[0].} @item{If @scheme[_C]'s first frame does not contain a mark keyed by @scheme[_k], then the mark list for @scheme[_C] is the mark list for @cont[0].} ] The @scheme[with-continuation-mark] form installs a mark on the first frame of the current continuation (see @secref["wcm"]). Procedures such as @scheme[current-continuation-marks] allow inspection of marks. Whenever Scheme creates an exception record for a primitive exception, it fills the @scheme[continuation-marks] field with the value of @scheme[(current-continuation-marks)], thus providing a snapshot of the continuation marks at the time of the exception. When a continuation procedure returned by @scheme[call-with-current-continuation] or @scheme[call-with-composable-continuation] is invoked, it restores the captured continuation, and also restores the marks in the continuation's frames to the marks that were present when @scheme[call-with-current-continuation] or @scheme[call-with-composable-continuation] was invoked. @defproc[(continuation-marks [cont (or/c continuation? thread?)] [prompt-tag prompt-tag? (default-continuation-prompt-tag)]) continuation-mark-set?]{ Returns an opaque value containing the set of continuation marks for all keys in the continuation @scheme[cont] (or the current continuation of @scheme[cont] if it is a thread) up to the prompt tagged by @scheme[prompt-tag]. If @scheme[cont] is an escape continuation (see @secref["prompt-model"]), then the current continuation must extend @scheme[cont], or the @exnraise[exn:fail:contract]. If @scheme[cont] was not captured with respect to @scheme[prompt-tag] and does not include a prompt for @scheme[prompt-tag], the @exnraise[exn:fail:contract]. If @scheme[cont] is a dead thread, the result is an empty set of continuation marks.} @defproc[(current-continuation-marks [prompt-tag prompt-tag? (default-continuation-prompt-tag)]) continuation-mark-set?]{ Returns an opaque value containing the set of continuation marks for all keys in the current continuation up to @scheme[prompt-tag]. In other words, it produces the same value as @schemeblock[ (call-with-current-continuation (lambda (k) (continuation-marks k prompt-tag)) prompt-tag) ]} @defproc[(continuation-mark-set->list [mark-set continuation-mark-set?] [key-v any/c] [prompt-tag prompt-tag? (default-continuation-prompt-tag)]) list?]{ Returns a newly-created list containing the marks for @scheme[key-v] in @scheme[mark-set], which is a set of marks returned by @scheme[current-continuation-marks]. The result list is truncated at the first point, if any, where continuation frames were originally separated by a prompt tagged with @scheme[prompt-tag]..} @defproc[(continuation-mark-set->list* [mark-set continuation-mark-set?] [key-list (listof any/c)] [none-v any/c #f] [prompt-tag prompt-tag? (default-continuation-prompt-tag)]) (listof vector?)]{ Returns a newly-created list containing vectors of marks in @scheme[mark-set] for the keys in @scheme[key-list], up to @scheme[prompt-tag]. The length of each vector in the result list is the same as the length of @scheme[key-list], and a value in a particular vector position is the value for the corresponding key in @scheme[key-list]. Values for multiple keys appear in a single vector only when the marks are for the same continuation frame in @scheme[mark-set]. The @scheme[none-v] argument is used for vector elements to indicate the lack of a value.} @defproc[(continuation-mark-set-first [mark-set (or/c continuation-mark-set? #f)] [key-v any/c] [prompt-tag prompt-tag? (default-continuation-prompt-tag)]) any]{ Returns the first element of the list that would be returned by @scheme[(continuation-mark-set->list (or mark-set (current-continuation-marks prompt-tag)) key-v prompt-tag)], or @scheme[#f] if the result would be the empty list. Typically, this result can be computed more quickly using @scheme[continuation-mark-set-first].} @defproc[(call-with-immediate-continuation-mark [key-v any/c] [proc (any/c . -> . any)] [default-v any/c #f]) any]{ Calls @scheme[proc] with the value associated with @scheme[key-v] in the first frame of the current continuation (i.e., a value that would be replaced if the call to @scheme[call-with-immediate-continuation-mark] were replaced with a @scheme[with-continuation-mark] form using @scheme[key-v] as the key expression). If no such value exists in the first frame, @scheme[default-v] is passed to @scheme[proc]. The @scheme[proc] is called in tail position with respect to the @scheme[call-with-immediate-continuation-mark] call. This function could be implemented with a combination of @scheme[with-continuation-mark], @scheme[current-continuation-marks], and @scheme[continuation-mark-set->list], but @scheme[call-with-immediate-continuation-mark] is implemented more efficiently; it inspects only the first frame of the current continuation.} @defproc[(continuation-mark-set? [v any/c]) boolean?]{ Returns @scheme[#t] if @scheme[v] is a mark set created by @scheme[continuation-marks] or @scheme[current-continuation-marks], @scheme[#f] otherwise.} @defproc[(continuation-mark-set->context [mark-set continuation-mark-set?]) list?]{ Returns a list representing an approximate ``@index["stack dump"]{@as-index{stack trace}}'' for @scheme[mark-set]'s continuation. The list contains pairs, where the @scheme[car] of each pair contains either @scheme[#f] or a symbol for a procedure name, and the @scheme[cdr] of each pair contains either @scheme[#f] or a @scheme[srcloc] value for the procedure's source location (see @secref["linecol"]); the @scheme[car] and @scheme[cdr] are never both @scheme[#f]. Conceptually, the stack-trace list is the result of @scheme[continuation-mark-set->list] with @scheme[mark-set] and Scheme's private key for procedure-call marks. The implementation may be different, however, and the results may merely approximate the correct answer. Thus, while the result may contain useful hints to humans about the context of an expression, it is not reliable enough for programmatic use. A stack trace is extracted from an exception and displayed by the default error display handler (see @scheme[error-display-handler]) for exceptions other than @scheme[exn:fail:user] (see @scheme[raise-user-error] in @secref["errorproc"]).} @examples[ (define (extract-current-continuation-marks key) (continuation-mark-set->list (current-continuation-marks) key)) (with-continuation-mark 'key 'mark (extract-current-continuation-marks 'key)) (with-continuation-mark 'key1 'mark1 (with-continuation-mark 'key2 'mark2 (list (extract-current-continuation-marks 'key1) (extract-current-continuation-marks 'key2)))) (with-continuation-mark 'key 'mark1 (with-continuation-mark 'key 'mark2 (code:comment @#,t{replaces previous mark}) (extract-current-continuation-marks 'key))) (with-continuation-mark 'key 'mark1 (list (code:comment @#,t{continuation extended to evaluate the argument}) (with-continuation-mark 'key 'mark2 (extract-current-continuation-marks 'key)))) (let loop ([n 1000]) (if (zero? n) (extract-current-continuation-marks 'key) (with-continuation-mark 'key n (loop (sub1 n))))) ]