14 Units
On this page:
top
up

14.6Contracts for UnitsπŸ”— i

There are a couple of ways of protecting units with contracts. One way is useful when writing new signatures, and the other handles the case when a unit must conform to an already existing signature.

14.6.1Adding Contracts to SignaturesπŸ”— i

When contracts are added to a signature, then all units which implement that signature are protected by those contracts. The following version of the toy-factory^ signature adds the contracts previously written in comments:

"contracted-toy-factory-sig.rkt"

(define-signature contracted-toy-factory^
[build-toys(->integer? (listoftoy?))]
[repaint(->toy?symbol? toy?)]
[toy?(->any/cboolean? )]
[toy-color(->toy?symbol? )])))
(provide contracted-toy-factory^)

Now we take the previous implementation of simple-factory@ and implement this version of toy-factory^ instead:

"contracted-simple-factory-unit.rkt"

(require "contracted-toy-factory-sig.rkt")
(define-unit contracted-simple-factory@
(import )
(export contracted-toy-factory^)
(printf "Factory started.\n")
(struct toy(color)#:transparent)
(define (build-toysn)
(for/list ([i(in-range n)])
(toy'blue)))
(define (repainttcol)
(toycol)))
(provide contracted-simple-factory@)

As before, we can invoke our new unit and bind the exports so that we can use them. This time, however, misusing the exports causes the appropriate contract errors.

> (require "contracted-simple-factory-unit.rkt")
> (define-values/invoke-unit/infer contracted-simple-factory@)

Factory started.

> (build-toys3)

(list (toy 'blue) (toy 'blue) (toy 'blue))

> (build-toys#f)

build-toys: contract violation

expected: integer?

given: #f

in: the 1st argument of

(-> integer? (listof toy?))

contract from:

(unit contracted-simple-factory@)

blaming: top-level

(assuming the contract is correct)

at: <collects>/racket/private/unit/exptime/import-export.r

kt:494:23

> (repaint3'blue)

repaint: contract violation

expected: toy?

given: 3

in: the 1st argument of

(-> toy? symbol? toy?)

contract from:

(unit contracted-simple-factory@)

blaming: top-level

(assuming the contract is correct)

at: <collects>/racket/private/unit/exptime/import-export.r

kt:494:23

14.6.2Adding Contracts to UnitsπŸ”— i

However, sometimes we may have a unit that must conform to an already existing signature that is not contracted. In this case, we can create a unit contract with unit/c or use the define-unit/contract form, which defines a unit which has been wrapped with a unit contract.

For example, here’s a version of toy-factory@ which still implements the regular toy-factory^, but whose exports have been protected with an appropriate unit contract.

"wrapped-simple-factory-unit.rkt"

(require "toy-factory-sig.rkt")
(define-unit/contract wrapped-simple-factory@
(import )
(export (toy-factory^
[build-toys(->integer? (listoftoy?))]
[repaint(->toy?symbol? toy?)]
[toy?(->any/cboolean? )]
[toy-color(->toy?symbol? )]))
(printf "Factory started.\n")
(struct toy(color)#:transparent)
(define (build-toysn)
(for/list ([i(in-range n)])
(toy'blue)))
(define (repainttcol)
(toycol)))
(provide wrapped-simple-factory@)
> (require "wrapped-simple-factory-unit.rkt")
> (define-values/invoke-unit/infer wrapped-simple-factory@)

Factory started.

toy?180: undefined;

cannot use before initialization

> (build-toys3)

(list (toy 'blue) (toy 'blue) (toy 'blue))

> (build-toys#f)

build-toys: contract violation

expected: integer?

given: #f

in: the 1st argument of

(-> integer? (listof toy?))

contract from:

(unit contracted-simple-factory@)

blaming: top-level

(assuming the contract is correct)

at: <collects>/racket/private/unit/exptime/import-export.r

kt:494:23

> (repaint3'blue)

repaint: contract violation

expected: toy?

given: 3

in: the 1st argument of

(-> toy? symbol? toy?)

contract from:

(unit contracted-simple-factory@)

blaming: top-level

(assuming the contract is correct)

at: <collects>/racket/private/unit/exptime/import-export.r

kt:494:23

top
up

AltStyle γ«γ‚ˆγ£γ¦ε€‰ζ›γ•γ‚ŒγŸγƒšγƒΌγ‚Έ (->γ‚ͺγƒͺγ‚ΈγƒŠγƒ«) /