[plt-scheme] unit system will change, SVN trunk will be unstable

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Wed Nov 29 19:24:26 EST 2006

We expect to merge Scott Owens's replacement for `(lib "unit.ss")' and
`(lib "unitsig.ss")' to the SVN trunk soon. It will probably take a few
days to get everything sorted out.

The new `(lib "unit.ss")' is an improved form of signed units without
an unsigned layer.

The old unit implementations will remain available as `(lib
"unit200.ss")' and `(lib "unitsig.ss")', but units provided by the
standard collections will use the new library instead of the old one.
In other words, you can continue with one of the old systems if your
use of units is independent of anyone else's; otherwise, you'll likely
be forced to change.

To give you an idea of what's coming, a typical conversion will be to
change

 (module M mzscheme
    (require (lib "unitsig.ss") ...)
    (provide u@)
    (define u@
      (unit/sig u^
        (import i^ ...)
        ...)))

to

 (module M mzscheme
    (require (lib "unit.ss") ...)  ; unit.ss, not unitsig.ss
    (provide u@)
    (define-unit u@                ; define-unit
      (import i^ ...)
      (export u^)                  ; export clause
      ...))

If `M' happens to be `u-unit', then you can reduce that to

 (module u-unit (lib "a-unit.ss") ; "a-unit.ss" as the language
   (require ...)                  ; things other than (lib "unit.ss")
   (import i^ ...)
   (export u^)
   ...)

On the signature side, it's mostly just a matter of changing `(lib
"unitsig.ss")' to `(lib "unit.ss")'. Again, if you have a `u-sig'
module that defines `u^':

  (module u-sig mzscheme
    (require (lib "unitsig.ss"))
    (define-signature u^
      (a 
       b
       c)))

you can write it as just

  (module u-sig (lib "a-signature.ss")
    a
    b
    c)

On the linking side, something like

 (define together@
   (compound-unit
     (import I)
     (link [A : a^ (a@ B C I)]
           [B : b^ (b@ A C I)]
           [C : c^ (c@ A B I)])
     (export (open A))))

will typically change to something like

  (define-compound-unit/infer together@
    (import I)
    (export a^)
    (link a@ b@ c@))

The `define-[compound-]unit' and `[define-]compound-unit/infer' forms
work together: links can be inferred when `define-' forms are used to
statically attach signature information to unit identifiers.

Similarly, when you want to invoke and flatten a unit like `together@'
into a definition context, you can use

 (define-values/invoke-unit/infer together@)

and both the imports (drawn from the enclosing context) and the defined
names are taken from the static binding of `together@'. If you want to
go the other direction, then `define-unit-from-context' can gather
bindings from the current context to create a unit with given export
signature.

Units are still first-class values, and you can use `define' instead of
`define-unit' to bind unit names. Inference only works with you have
static unit bindings. Without inference, linking in a `compound-unit'
expression is similar to before.

There are many technical changes beneath the surface change. In
particular, signatures are matched by name (rather than by structure),
a unit can implement multiple signatures (instead of exporting
sub-units), and unit signatures are macro-extensible.

Matthew



Posted on the users mailing list.