► |  | The Racket Reference

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 and Parallelism
11 | Macros
12 | Input and Output
13 | Reflection and Security
14 | Operating System
15 | Memory Management
16 | Unsafe Operations
17 | Running Racket
| Bibliography
| Index

▼ | 7 | Contracts

7.1 | Data-structure Contracts
7.2 | Function Contracts
7.3 | Parametric Contracts
7.4 | Lazy Data-structure Contracts
7.5 | Structure Type Property Contracts
7.6 | Attaching Contracts to Values
7.7 | Building New Contract Combinators
7.8 | Contract Utilities
7.9 | racket/ contract/ base
7.10 | Legacy Contracts
7.11 | Random generation

On this page:

struct-type-property/ c

Version: 5.3
top← prev up next →

#### 7.5`` Structure Type Property Contracts

> > procedure

> > (struct-type-property/c value-contract) → contract?

> value-contract : contract?

Produces a contract for a structure type property. When the contract is applied to a struct type property, it produces a wrapped struct type property that applies value-contract to the value associated with the property when it used to create a new struct type (via struct, make-struct-type, etc).

The struct type property’s accessor function is not affected; if it is exported, it must be protected separately.

As an example, consider the following module. It creates a structure type property, prop, whose value should be a function mapping a structure instance to a numeric predicate. The module also exports app-prop, which extracts the predicate from a structure instance and applies it to a given value.

> > (module propmod racket
> (require racket/contract)
> (define-values (prop prop? prop-ref)
> (make-struct-type-property 'prop))
> (define (app-prop x v)
> (((prop-ref x) x) v))
> (provide/contract
> [prop? (-> any/c boolean?)]
> [prop (struct-type-property/c
> (-> prop? (-> integer? boolean?)))]
> [app-prop (-> prop? integer? boolean?)])
> (provide prop-ref))

The structmod module creates a structure type named s with a single field; the value of prop is a function that extracts the field value from an instance. Thus the field ought to be an integer predicate, but notice that structmod places no contract on s enforcing that constraint.

> > (module structmod racket
> (require 'propmod)
> (struct s (f) #:property prop (lambda (s) (s-f s)))
> (provide (struct-out s)))

> > (require 'propmod 'structmod)

First we create an s instance with a integer predicate, so the constraint on prop is in fact satisfied. The first call to app-prop is correct; the second simply violates the contract of app-prop.

> > (define s1 (s even?))

> > (app-prop s1 5)
> #f
> > (app-prop s1 'apple)
> app-prop: contract violation
> expected: integer?, given: 'apple
> in: the 2nd argument of
> (-> prop? integer? boolean?)
> contract from: propmod
> blaming: top-level
> at: eval:2.0

We are able to create s instances with values other than integer predicates, but applying app-prop on them blames structmod, because the function associated with prop—that is, (lambda (s) (s-f s))—does not always produce a value satisfying (-> integer? boolean?).

> > (define s2 (s "not a fun"))

> > (app-prop s2 5)
> prop: contract violation
> expected a procedure that accepts 1 mandatory argument
> without any keywords, given: "not a fun"
> in: the range of
> ...
> (struct-type-property/c
> (-> prop? (-> integer? boolean?)))
> contract from: propmod
> blaming: structmod
> at: eval:2.0
> > (define s3 (s list))

> > (app-prop s3 5)
> prop: contract violation
> expected: boolean?, given: '(5)
> in: the range of
> the range of
> ...
> (struct-type-property/c
> (-> prop? (-> integer? boolean?)))
> contract from: propmod
> blaming: structmod
> at: eval:2.0

The fix would be to propagate the obligation inherited from prop to s:

> (provide (contract-out
> [struct s ([f (-> integer? boolean?)])]))

Finally, if we directly apply the property accessor, prop-ref, and then misuse the resulting function, the propmod module is blamed:

> > ((prop-ref s3) 'apple)
> prop: broke its contract
> promised: prop?, produced: 'apple
> in: the 1st argument of
> ...
> (struct-type-property/c
> (-> prop? (-> integer? boolean?)))
> contract from: propmod
> blaming: propmod
> at: eval:2.0

The propmod module has an obligation to ensure a function associated with prop is applied only to values satisfying prop?. By directly providing prop-ref, it enables that constraint to be violated (and thus it is blamed), even though the bad application actually occurs elsewhere.

Generally there is no need to provide a structure type property accessor at all; it is typically only used by other functions within the module. But if it must be provided, it should be protected thus:

> (provide (contract-out
> [prop-ref (-> prop? (-> prop? (-> integer? boolean?)))]))

top← prev up next →