diff --git a/collects/scribblings/reference/chaperones.scrbl b/collects/scribblings/reference/chaperones.scrbl index 88568d29f3..6e85707911 100644 --- a/collects/scribblings/reference/chaperones.scrbl +++ b/collects/scribblings/reference/chaperones.scrbl @@ -369,6 +369,45 @@ or override impersonator-property values of @racket[prompt-tag]. } +@defproc[(impersonate-continuation-mark-key + [key continuation-mark-key?] + [get-proc procedure?] + [set-proc procedure?] + [prop impersonator-property?] + [prop-val any] ... ...) + (and/c continuation-mark? impersonator?)]{ + +Returns an impersonator of @racket[key], which redirects +@racket[with-continuation-mark] and continuation mark accessors such +as @racket[continuation-mark-set->list]. + +The @racket[get-proc] must accept the the value attached to a +continuation mark and it must produce a replacement +value, which will be returned by the continuation mark accessor. + +The @racket[set-proc] must accept a value passed to +@racket[with-continuation-mark]; it must produce a replacement +value, which is attached to the continuation frame. + +Pairs of @racket[prop] and @racket[prop-val] (the number of arguments +to @racket[impersonate-prompt-tag] must be odd) add impersonator properties +or override impersonator-property values of @racket[key]. + +@examples[ + (define mark-key + (impersonate-continuation-mark-key + (make-continuation-mark-key) + (lambda (l) (map char-upcase l)) + (lambda (s) (string->list s)))) + + (with-continuation-mark mark-key "quiche" + (continuation-mark-set-first + (current-continuation-marks) + mark-key)) +] +} + + @defthing[prop:impersonator-of struct-type-property?]{ A @tech{structure type property} (see @secref["structprops"]) that @@ -601,6 +640,51 @@ the same values or chaperones of the values that it is given. ] } + +@defproc[(chaperone-continuation-mark-key + [key continuation-mark-key?] + [get-proc procedure?] + [set-proc procedure?] + [prop impersonator-property?] + [prop-val any] ... ...) + (and/c continuation-mark-key? chaperone?)]{ + +Like @racket[impersonate-continuation-mark-key], but produces a +chaperoned value. The @racket[get-proc] procedure must produce the +same value or a chaperone of the original value, and @racket[set-proc] +must produce the same value or a chaperone of the value that it is +given. + +@examples[ + (define bad-chaperone + (chaperone-continuation-mark-key + (make-continuation-mark-key) + (lambda (l) (map char-upcase l)) + string->list)) + + (with-continuation-mark bad-chaperone "timballo" + (continuation-mark-set-first + (current-continuation-marks) + bad-chaperone)) + + (define (checker s) + (if (> (string-length s) 5) + s + (error "expected string of length at least 5"))) + + (define good-chaperone + (chaperone-continuation-mark-key + (make-continuation-mark-key) + checker + checker)) + + (with-continuation-mark good-chaperone "zabaione" + (continuation-mark-set-first + (current-continuation-marks) + good-chaperone)) +] +} + @; ------------------------------------------------------------ @section{Impersonator Properties} diff --git a/collects/scribblings/reference/cont-marks.scrbl b/collects/scribblings/reference/cont-marks.scrbl index 786fd5132f..e958474b69 100644 --- a/collects/scribblings/reference/cont-marks.scrbl +++ b/collects/scribblings/reference/cont-marks.scrbl @@ -87,6 +87,19 @@ in @racket[mark-set], which is a set of marks returned by the first point, if any, where continuation frames were originally separated by a prompt tagged with @racket[prompt-tag].} +@defproc*[([(make-continuation-mark-key) continuation-mark-key?] + [(make-continuation-mark-key [sym symbol?]) continuation-mark-key?])]{ +Creates a continuation mark key that is not @racket[equal?] to the result +of any other value (including prior and future results from +@racket[make-continuation-mark-key]). The continuation mark key can be used +as the key argument for @racket[with-continuation-mark] or accessor procedures +like @racket[continuation-mark-set-first]. The mark key can be chaperoned +or impersonated, unlike other values that are used as the mark key. + +The optional @racket[sym] argument, if provided, is used when printing +the continuation mark. +} + @defproc[(continuation-mark-set->list* [mark-set continuation-mark-set?] [key-list (listof any/c)] @@ -140,6 +153,10 @@ and @racket[continuation-mark-set->list], but efficiently; it inspects only the first frame of the current continuation.} +@defproc[(continuation-mark-key? [v any/c]) boolean?]{ +Returns @racket[#t] if @racket[v] is a mark key created by +@racket[make-continuation-mark-key], @racket[#f] otherwise.} + @defproc[(continuation-mark-set? [v any/c]) boolean?]{ Returns @racket[#t] if @racket[v] is a mark set created by @racket[continuation-marks] or @racket[current-continuation-marks], diff --git a/collects/scribblings/reference/contracts.scrbl b/collects/scribblings/reference/contracts.scrbl index 12f065579f..710fe72a5f 100644 --- a/collects/scribblings/reference/contracts.scrbl +++ b/collects/scribblings/reference/contracts.scrbl @@ -520,6 +520,30 @@ an @tech{impersonator} contract. } +@defproc[(continuation-mark/c [contract contract?]) contract?]{ +Takes a single contract and returns a contract that recognizes +continuation marks and will check any mappings of marks to values +or any accesses of the mark value. + +If the argument @racket[contract] is a chaperone contract, the resulting +contract will also be a @tech{chaperone} contract. Otherwise, the contract is +an @tech{impersonator} contract. + +@examples[#:eval (contract-eval) + (define/contract mark-key + (continuation-mark/c (-> symbol (listof symbol?))) + (make-continuation-mark-key)) + + (with-continuation-mark + mark-key + (lambda (s) (append s '(truffle fudge ganache))) + (let ([mark-value (continuation-mark-set-first + (current-continuation-marks) mark-key)]) + (mark-value "chocolate-bar"))) +] +} + + @defform[(flat-rec-contract id flat-contract-expr ...)]{ Constructs a recursive @tech{flat contract}. A