Version: 4.1

14.1 Signatures and Units

The interface of a unit is described in terms of signatures. Each signature is defined (normally within a module) using define-signature. For example, the following signature, placed in a "toy-factory-sig.ss" file, describes the exports of a component that implements a toy factory:

By convention, signature names with ^.

  ; In "toy-factory-sig.ss":

  #lang scheme

  

  (define-signature toy-factory^

    (build-toys  ; (integer? -> (listof toy?))

     repaint     ; (toy? symbol? -> toy?)

     toy?        ; (any/c -> boolean?)

     toy-color)) ; (toy? -> symbol?)

  

  (provide toy-factory^)

An implementation of the toy-factory^ signature is written using define-unit with an export clause that names toy-factory^:

By convention, unit names with @.

  ; In "simple-factory-unit.ss":

  #lang scheme

  

  (require "toy-factory-sig.ss")

  

  (define-unit simple-factory@

    (import)

    (export toy-factory^)

  

    (printf "Factory started.\n")

  

    (define-struct toy (color) #:transparent)

  

    (define (build-toys n)

      (for/list ([i (in-range n)])

        (make-toy 'blue)))

  

    (define (repaint t col)

      (make-toy col)))

  

  (provide simple-factory@)

The toy-factory^ signature also could be referenced by a unit that needs a toy factory to implement something else. In that case, toy-factory^ would be named in an import clause. For example, a toy store would get toys from a toy factory. (Suppose, for the sake of an example with interesting features, that the store is willing to sell only toys in a particular color.)

  ; In "toy-store-sig.ss":

  #lang scheme

  

  (define-signature toy-store^

    (store-color     ; (-> symbol?)

     stock!          ; (integer? -> void?)

     get-inventory)) ; (-> (listof toy?))

  

  (provide toy-store^)

  ; In "toy-store-unit.ss":

  #lang scheme

  

  (require "toy-store-sig.ss"

           "toy-factory-sig.ss")

  

  (define-unit toy-store@

    (import toy-factory^)

    (export toy-store^)

  

    (define inventory null)

  

    (define (store-color) 'green)

  

    (define (maybe-repaint t)

      (if (eq? (toy-color t) (store-color))

          t

          (repaint t (store-color))))

  

    (define (stock! n)

      (set! inventory

            (append inventory

                    (map maybe-repaint

                         (build-toys n)))))

  

    (define (get-inventory) inventory))

  

  (provide toy-store@)

Note that "toy-store-unit.ss" imports "toy-factory-sig.ss", but not "simple-factory-unit.ss". Consequently, the toy-store@ unit relies only on the specification of a toy factory, not on a specific implementation.