13.5 Proxies and Chaperones

► |  | Reference: Racket

1 | Language Model
2 | Syntactic Forms
3 | Datatypes
4 | Structures
5 | Classes and Objects
6 | Units
7 | Contracts
8 | Pattern Matching
9 | Control Flow
10 | Concurrency
11 | Macros
12 | Input and Output
13 | Reflection and Security
14 | Operating System
15 | Memory Management
16 | Unsafe Operations
17 | Running Racket
| Bibliography
| Index

▼ | 13 | Reflection and Security

13.1 | Namespaces
13.2 | Evaluation and Compilation
13.3 | The racket/ load Language
13.4 | Module Names and Loading
13.5 | Proxies and Chaperones
13.6 | Security Guards
13.7 | Custodians
13.8 | Thread Groups
13.9 | Structure Inspectors
13.10 | Code Inspectors
13.11 | Sandboxed Evaluation

► | 13.5 | Proxies and Chaperones

13.5.1 | Proxy Constructors
13.5.2 | Chaperone Constructors
13.5.3 | Proxy Properties

On this page:

proxy?
chaperone?
proxy-of?
chaperone-of?
13.5.1`` Proxy Constructors
proxy-procedure
proxy-struct
proxy-vector
proxy-box
proxy-hash
13.5.2`` Chaperone Constructors
chaperone-procedure
chaperone-struct
chaperone-vector
chaperone-box
chaperone-hash
chaperone-struct-type
chaperone-evt
13.5.3`` Proxy Properties
make-proxy-property
proxy-property?
proxy-property-accessor-procedure?

top← prev up next →

#### 13.5`` Proxies and Chaperones

A proxy is a wrapper for a value where the wrapper redirects certain of the value’s operations. Proxies apply only to procedures, structures for which an accessor or mutator is available, structure types, hash tables, vectors, and boxes. A proxied value is equal? to the original value, but not eq? to the original value.

A chaperone is a kind of proxy whose refinement of a value’s operation is restricted to side effects (including, in particular, raising an exception) or chaperoning values supplied to or produced by the operation. For example, a vector chaperone can redirect vector-ref to raise an exception if the accessed vector slot contains a string, or it can cause the result of vector-ref to be a chaperoned variant of the value that is in the accessed vector slot, but it cannot redirect vector-ref to produce a value that is arbitrarily different from the value in the vector slot.

A non-chaperone proxy, in contrast, can refine an operation to swap one value for any another. A proxy cannot be applied to an immutable value or refine the access to an immutable field in an instance of a structure type, since arbitrary replacement of an operation’s value amounts to mutation of the proxied value.

Beware that each of the following operations can be redirected to arbitrary procedure through proxies on the operation’s argument – assuming that the operation is available to the creator of the proxy:

- a structure-field accesor

- a structure-field mutator

- a structure type property accessor

- application of a procedure

- unbox

- set-box!

- vector-ref

- vector-set!

- hash-ref

- hash-set

- hash-set!

- hash-remove

- hash-remove!

Derived operations, such as printing a value, can be redirected through proxies due to their use of accessor functions. The equal?, equal-hash-code, and equal-secondary-hash-code operations, in contrast, may bypass proxies (but they are not obliged to).

In addition to redirecting operations that work on a value, a proxy can include proxy properties for a proxied value. A proxy property is similar to a structure type property, but it applies to chaperones instead of structure types and their instances.

( proxy? v) → boolean?
v : any/c

Returns #t if v is a proxy, #f otherwise.

Programs and libraries generally should avoid proxy? and treat proxies the same as unproxied values. In rare cases, proxy? may be needed to guard against redirection by a proxy of an operation to an arbitrary procedure.

( chaperone? v) → boolean?
v : any/c

Returns #t if v is a chaperone, #f otherwise.

Programs and libraries generally should avoid chaperone? for the same reason that they should avoid proxy?.

( proxy-of? v1 v2) → boolean?
v1 : any/c
v2 : any/c

Indicates whether v1 can be considered equivalent modulo proxies to v2.

For values that include no proxies, v1 and v2 can be considered proxies of each other if they are equal?.

Otherwise, all proxies of v2 must be intact in v1, in the sense that parts of v2 must be derived from v1 through one of the proxy constructors (e.g., proxy-procedure or chaperone-procedure).

( chaperone-of? v1 v2) → boolean?
v1 : any/c
v2 : any/c

Indicates whether v1 can be considered equivalent modulo chaperones to v2.

For values that include no chaperones, v1 and v2 can be considered chaperones of each other if they are equal?, except that the mutability of vectors and boxes with v1 and v2 must be the same.

Otherwise, all chaperones of v2 must be intact in v1, in the sense that parts of v2 must be derived from v1 through one of the chaperone constructors (e.g., chaperone-procedure).

##### 13.5.1`` Proxy Constructors

( proxy-procedure |  | proc |  |  |  |
|  | wrapper-proc |  |  |  |
|  | prop |  |  |  |
|  | prop-val ... |  |  |  |
|  | ...) |  | → |  | ( and/c procedure? proxy?)

proc : procedure?
wrapper-proc : procedure?
prop : proxy-property?
prop-val : any

Returns a proxied procedure that has the same arity, name, and other attributes as proc. When the proxied procedure is applied, the arguments are first passed to wrapper-proc, and then the results from wrapper-proc are passed to proc. The wrapper-proc can also supply a procedure that processes the results of proc.

The arity of wrapper-proc must include the arity of proc. The allowed keyword arguments of wrapper-proc must be a superset of the allowed keywords of proc. The required keyword arguments of wrapper-proc must be a subset of the required keywords of proc.

For applications without keywords, the result of wrapper-proc must be either the same number of values as supplied to it or one more than the number of supplied values, where an extra result is supplied before the others. The additional result, if any, must be a procedure that accepts as many results as produced by proc; it must return the same number of results. If wrapper-proc returns the same number of values as it is given (i.e., it does not return a procedure to proxy proc’s result), then proc is called in tail position with respect to the call to the proxy.

For applications that include keyword arguments, wrapper-proc must return an additional value before any other values but after the result-proxying procedure (if any). The additional value must be a list of proxys of the keyword arguments that were supplied to the proxied procedure (i.e., not counting optional arguments that were not supplied). The arguments must be ordered according to the sorted order of the supplied arguments’ keywords.

Pairs of prop and prop-val (the number of arguments to procedure-proxy must be even) add proxy properties or override proxy-property values of proc.

( proxy-struct |  | v |  |  |  |
|  | orig-proc |  |  |  |
|  | redirect-proc ... |  |  |  |
|  | ... |  |  |  |
|  | prop |  |  |  |
|  | prop-val ... |  |  |  |
|  | ...) |  | → |  | any/c

v : any/c

orig-proc

:

( or/c struct-accessor-procedure?
struct-mutator-procedure?)

redirect-proc : procedure?
prop : proxy-property?
prop-val : any

Returns a proxied value like v, but with certain operations on the proxied redirected. The orig-procs indicate the operations to redirect, and the corresponding redirect-procs supply the redirections.

The protocol for a redirect-proc depends on the corresponding orig-proc:

- A structure-field: redirect-proc must accept two arguments, v and the value field-v that orig-proc produces for v; it must return a replacement for field-v. The corresponding field must not be immutable.

- A structure field mutator: redirect-proc must accept two arguments, v and the value field-v supplied to the mutator; it must return a replacement for field-v to be propagated to orig-proc and v.

Pairs of prop and prop-val (the number of arguments to proxy-procedure must be odd) add proxy properties or override proxy-property values of v.

( proxy-vector |  | vec |  |  |  |
|  | ref-proc |  |  |  |
|  | set-proc |  |  |  |
|  | prop |  |  |  |
|  | prop-val ... |  |  |  |
|  | ...) |  | → |  | ( and/c vector? proxy?)

vec : ( and/c vector? ( not/c immutable?))
ref-proc : ( vector? exact-nonnegative-integer? any/c . -> . any/c)
set-proc : ( vector? exact-nonnegative-integer? any/c . -> . any/c)
prop : proxy-property?
prop-val : any

Returns a proxied value like vec, but with vector-ref and vector-set! operations on the proxied vector redirected.

The ref-proc must accept vec, an index passed to vector-ref, and the value that vector-ref on vec produces for the given index; it must produce a replacement for the value, which is the result of vector-ref on the proxy.

The set-proc must accept vec, an index passed to vector-set!, and the value passed to vector-set!; it must produce a replacement for the value, which is used with vector-set! on the original vec to install the value.

Pairs of prop and prop-val (the number of arguments to proxy-vector must be odd) add proxy properties or override proxy-property values of vec.

( proxy-box |  | box |  |  |  |
|  | unbox-proc |  |  |  |
|  | set-proc |  |  |  |
|  | prop |  |  |  |
|  | prop-val ... |  |  |  |
|  | ...) |  | → |  | ( and/c box? proxy?)

box : ( and/c box? ( not/c immutable?))
unbox-proc : ( box? any/c . -> . any/c)
set-proc : ( box? any/c . -> . any/c)
prop : proxy-property?
prop-val : any

Returns a proxied value like bx, but with unbox and set-box! operations on the proxied box redirected.

The unbox-proc must accept bx and the value that unbox on bx produces index; it must produce a replacement value, which is the result of unbox on the proxy.

The set-proc must accept bx and the value passed to set-box!; it must produce a replacement value, which is used with set-box! on the original bx to install the value.

Pairs of prop and prop-val (the number of arguments to proxy-box must be odd) add proxy properties or override proxy-property values of bx.

( proxy-hash |  | hash |  |  |  |
|  | ref-proc |  |  |  |
|  | set-proc |  |  |  |
|  | remove-proc |  |  |  |
|  | key-proc |  |  |  |
|  | prop |  |  |  |
|  | prop-val ... |  |  |  |
|  | ...) |  | → |  | ( and/c hash? proxy?)

hash : ( and/c hash? ( not/c immutable?))

ref-proc

:

( hash? any/c . -> . ( values
any/c
( hash? any/c any/c . -> . any/c)))

set-proc : ( hash? any/c any/c . -> . ( values any/c any/c))
remove-proc : ( hash? any/c . -> . any/c)
key-proc : ( hash? any/c . -> . any/c)
prop : proxy-property?
prop-val : any

Returns a proxied value like hash, but with hash-ref, hash-set! or hash-set (as applicable) and hash-remove or hash-remove! (as application) operations on the proxied hash table redirected. When hash-set or hash-remove is used on a proxied hash table, the resulting hash table is given all of the proxys of the given hash table. In addition, operations like hash-iterate-key or hash-map, which extract keys from the table, use key-proc to filter keys extracted from the table. Operations like hash-iterate-value or hash-iterate-map implicitly use hash-ref and therefore redirect through ref-proc.

The ref-proc must accept hash and a key passed hash-ref. It must return a replacement key as well as a procedure. The returned procedure is called only if the returned key is found in hash via hash-ref, in which case the procedure is called with hash, the previously returned key, and the found value. The returned procedure must itself return a replecement for the found value.

The set-proc must accept hash, a key passed to hash-set! or hash-set, and the value passed to hash-set! or hash-set; it must produce two values: a replacement for the key and a replacement for the value. The returned key and value are used with hash-set! or hash-set on the original hash to install the value.

The remove-proc must accept hash and a key passed to hash-remove! or hash-remove; it must produce the a replacement for the key, which is used with hash-remove! or hash-remove on the original hash to remove any mapping using the (proxy-replaced) key.

The key-proc must accept hash and a key that has been extracted from hash (by hash-iterate-key or other operations that use hash-iterate-key internally); it must produce a replacement for the key, which is then reported as a key extracted from the table.

Pairs of prop and prop-val (the number of arguments to proxy-hash must be odd) add proxy properties or override proxy-property values of hash.

##### 13.5.2`` Chaperone Constructors

( chaperone-procedure |  | proc |
|  | wrapper-proc |
|  | prop |
|  | prop-val ... |
|  | ...) |

→ ( and/c procedure? chaperone?)
proc : procedure?
wrapper-proc : procedure?
prop : proxy-property?
prop-val : any

Like proxy-procedure, but for each value supplied to wrapper-proc, the corresponding result must be the same or a chaperone of (in the sense of chaperone-of?) the supplied value. The additional result, if any, that precedes the chaperoned values must be a procedure that accepts as many results as produced by proc; it must return the same number of results, each of which is the same or a chaperone of the corresponding original result.

For applications that include keyword arguments, wrapper-proc must return an additional value before any other values but after the result-chaperoning procedure (if any). The additional value must be a list of chaperones of the keyword arguments that were supplied to the chaperoned procedure (i.e., not counting optional arguments that were not supplied). The arguments must be ordered according to the sorted order of the supplied arguments’ keywords.

( chaperone-struct |  | v |  |  |  |
|  | orig-proc |  |  |  |
|  | redirect-proc ... |  |  |  |
|  | ... |  |  |  |
|  | prop |  |  |  |
|  | prop-val ... |  |  |  |
|  | ...) |  | → |  | any/c

v : any/c

orig-proc

:

( or/c struct-accessor-procedure?
struct-mutator-procedure?
struct-type-property-accessor-procedure?
( one-of/c struct-info))

redirect-proc : procedure?
prop : proxy-property?
prop-val : any

Like proxy-struct, but with the following refinements:

- With a structure-field accessor as orig-proc, redirect-proc must accept two arguments, v and the value field-v that orig-proc produces for v; it must return chaperone of field-v. The corresponding field may be immutable.

- A property accessor can be supplied as orig-proc. The corresponding redirect-proc uses the same protocol as for a structure-field selector.

- With structure-field mutator as orig-proc, redirect-proc must accept two arguments, v and the value field-v supplied to the mutator; it must return chaperone of field-v to be propagated to orig-proc and v.

- With struct-info as orig-proc, the corresponding redirect-proc must accept two values, which are the results of struct-info on v; it must return each values or a chaperone of each value. The redirect-proc is not called if struct-info would return #f as its first argument.

An orig-proc can be struct-info only if some other orig-proc is supplied, and each orig-proc must indicate a distinct operation. If no orig-procs are supplied, then no props must be supplied, and v is returned unchaperoned.

( chaperone-vector |  | vec |  |  |  |
|  | ref-proc |  |  |  |
|  | set-proc |  |  |  |
|  | prop |  |  |  |
|  | prop-val ... |  |  |  |
|  | ...) |  | → |  | ( and/c vector? chaperone?)

vec : vector?
ref-proc : ( vector? exact-nonnegative-integer? any/c . -> . any/c)
set-proc : ( vector? exact-nonnegative-integer? any/c . -> . any/c)
prop : proxy-property?
prop-val : any

Like proxy-vector, but with support for mutable vectors. The ref-proc procedure must produce the same value or a chaperone of the original value, and set-proc must produce the value that is given or a chaperone of the value. The set-proc will not be used if vec is immutable.

( chaperone-box |  | bx |  |  |  |
|  | unbox-proc |  |  |  |
|  | set-proc |  |  |  |
|  | prop |  |  |  |
|  | prop-val ... |  |  |  |
|  | ...) |  | → |  | ( and/c box? chaperone?)

bx : box?
unbox-proc : ( box? any/c . -> . any/c)
set-proc : ( box? any/c . -> . any/c)
prop : proxy-property?
prop-val : any

Like prox-box, but with support for immutable boxes. The unbox-proc procedure must produce the same value or a chaperone of the original value, and set-proc must produce the same value or a chaperone of the value that it is given. The set-proc will not be used if bx is immutable.

( chaperone-hash |  | hash |  |  |  |
|  | ref-proc |  |  |  |
|  | set-proc |  |  |  |
|  | remove-proc |  |  |  |
|  | key-proc |  |  |  |
|  | prop |  |  |  |
|  | prop-val ... |  |  |  |
|  | ...) |  | → |  | ( and/c hash? chaperone?)

hash : hash?

ref-proc

:

( hash? any/c . -> . ( values
any/c
( hash? any/c any/c . -> . any/c)))

set-proc : ( hash? any/c any/c . -> . ( values any/c any/c))
remove-proc : ( hash? any/c . -> . any/c)
key-proc : ( hash? any/c . -> . any/c)
prop : proxy-property?
prop-val : any

Like proxy-hash, but with constraints on the given functions and support for immutable hashes. The ref-proc procedure must return a found value or a chaperone of the value. The set-proc procedure must produce two values: the key that it is given or a chaperone of the key and the value that it is given or a chaperone of the value. The remove-proc and key-proc procedures must produce the given key or a chaperone of the key.

( chaperone-struct-type |  | struct-type |
|  | struct-info-proc |
|  | make-constructor-proc |
|  | guard-proc |
|  | prop |
|  | prop-val ... |
|  | ...) |

→ ( and/c struct-type? chaperone?)
struct-type : struct-type?
struct-info-proc : procedure?
make-constructor-proc : ( procedure? . -> . procedure?)
guard-proc : procedure?
prop : proxy-property?
prop-val : any

Returns a chaperoned value like struct-type, but with struct-type-info and struct-type-make-constructor operations on the chaperoned structure type redirected. In addition, when a new structure type is created as a subtype of the chaperoned structure type, guard-proc is interposed as an extra guard on creation of instances of the subtype.

The struct-info-proc must accept 8 arguments – the result of struct-type-info on struct-type. It must return 8 values, where each is the same or a chaperone of the corresponding argument. The 8 values are used as the results of struct-type-info for the chaperoned structure type.

The make-constructor-proc must accept a single procedure argument, which is a constructor produced by struct-type-make-constructor on struct-type. It must return the same or a chaperone of the procedure, which is used as the result of struct-type-make-constructor on the chaperoned structure type.

The guard-proc must accept as many argument as a constructor for struct-type; it must return the same number of arguments, each the same or a chaperone of the corresponding argument. The guard-proc is added as a constructor guard when a subtype is created of the chaperoned structure type.

Pairs of prop and prop-val (the number of arguments to chaperone-struct-type must be even) add proxy properties or override proxy-property values of struct-type.

( chaperone-evt evt proc prop prop-val ... ...)
→ ( and/c evt? chaperone?)
evt : evt?
proc : ( evt? . -> . ( values evt? ( any/c . -> . any/c)))
prop : proxy-property?
prop-val : any

Returns a chaperoned value like evt, but with proc as an event generator when the result is synchronized with functions like sync.

The proc generator is called on synchronization, much like the procedure passed to guard-evt, except that proc is given evt. The proc must return two values: a synchronizable event that is a chaperone of evt, and a procedure that is used to check the event’s result if it is chosen in a selection. The latter procedure accepts the result of evt, and it must return a chaperone of that value.

Pairs of prop and prop-val (the number of arguments to chaperone-struct-type must be even) add proxy properties or override proxy-property values of evt.

##### 13.5.3`` Proxy Properties

( make-proxy-property name)

→

proxy-property?
(-> any/c boolean?)
(-> chaperone? any)

name : symbol?

Creates a new proxy property and returns three values:

- a proxy property descriptor, for use with chaperone-procedure, chaperone-struct, and other chaperone constructors;

- a proxy property predicate procedure, which takes an arbitrary value and returns #t if the value is a chaperone with a value for the property, #f otherwise;

- an proxy property accessor procedure, which returns the value associated with a chaperone for the property; if a value given to the accessor is not a chaperone or does not have a value for the property (ie if the corresponding chaperone property predicate returns #f), the accessor raises exn:fail:contract exception is raised.

( proxy-property? v) → boolean?
v : any/c

Returns #t if v is a proxy property descriptor value, #f otherwise.

( proxy-property-accessor-procedure? v) → boolean?
v : any/c

Returns #t if v is an accessor procedure produced by make-proxy-property, #f otherwise.
top← prev up next →