Version: 4.2.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.