s c h e m a t i c s : c o o k b o o k

/ Cookbook.UnitSig

This Web


WebHome 
WebChanges 
TOC (with recipes)
NewRecipe 
WebTopicList 
WebStatistics 

Other Webs


Chicken
Cookbook
Erlang
Know
Main
Plugins
Sandbox
Scm
TWiki  

Schematics


Schematics Home
Sourceforge Page
SchemeWiki.org
Original Cookbook
RSS

Scheme Links


Schemers.org
Scheme FAQ
R5RS
SRFIs
Scheme Cross Reference
PLT Scheme SISC
Scheme48 SCM
MIT Scheme scsh
JScheme Kawa
Chicken Guile
Bigloo Tiny
Gambit LispMe
GaucheChez

Lambda the Ultimate
TWiki.org

Creating and using a Signed Unit

Problem

You want to create something like a module, but incomplete, so that some functionality is defined elsewhere and imported at compile-time. What's more, you don't want to worry about circular references, where module a refers to module b which refers to some part of module a.

Signed units are PLT scheme's implementation of functors, and are essentially composable classes for those people who rest firmly in the OO world; classes with mixins, but a little more flexible than that. They're not intended to replace modules, but rather complement them. To start using signed units, the first step is to require unitsig.ss.

Solution

> (require (lib "unitsig.ss"))

To create a signed unit, the first thing you need is a signature, which is a single form containing all the symbols that your unit will import or all the symbols your unit will export, or some subset of either of those. So if your unit imports the symbols:

and you want to export the symbols

Your signatures can look like this

> (define-signature acting-troupe^ (graham-chapman john-cleese eric-idle michael-palin))
> (define-signature silly-movie^ (monty-python and-the-holy-grail))

The circumflex at the end means nothing to unit/sig -- it's just syntactic sugar that has become a kind of standard convention when working with units. When I said that they can be subsets earlier, I meant I could have split the first signature or second signature into two separate signatures, something along the lines of:

(define-signature bird-watcher^ (michael-palin))
(define-signature Q^ (john-cleese))
(define-signature everyone-else^ (graham-chapman eric-idle))

And it would have been logically the same. The only thing to remember here is to not mix your export and import signatures, as that will be important later. Now, to go about defining that unit.

> (define movie@
   (unit/sig silly-movie^
     (import acting-troupe^)

     (define (monty-python)
       (print graham-chapman)
       (print john-cleese)
       (print eric-idle)
       (print michael-palin))

     (define (and-the-holy-grail)
         (print 'coconuts)
         (print 'boring-historian)
         (print 'bring-out-your-dead)
         (print 'scene-24)
         (print 'and-so-on))))

And that's it -- you have a signed unit. It's incomplete, though, because we haven't defined our actors yet. These are actually either defined as a separate unit or defined at the top level. Let's take the case where they're defined as a separate unit, though, because this is effectively a functor, which is a very tidy way of composing programs from components.

> (define actors@
   (unit/sig acting-troupe^
      (import)

      (define graham-chapman 'arthur)
      (define michael-palin 'galahad)
      (define john-cleese 'lancelot)
      (define eric-idle 'robin)))

Not bad. Note the differences with the movie@ unit. Most importantly, import is completely bare, which means that no other symbols are needed to make actors@ complete. Note also that every symbol specified in the acting-troupe^ signature is defined here in the module. So let's do the obvious thing:

> (invoke-unit/sig actors@)
> (invoke-unit/sig movie@ acting-troupe^)

Eek! That produced an error that our symbols were undefined. Let's look at why. Invoking units with invoke-unit or invoke-unit/sig does not define anything at the top level. Exports are only meant to be exported to other units. There is a function (define-values/invoke-unit/sig) which when used in place of invoke-unit/sig will define the symbols from actors@ -- all the symbols needed for acting-troupe at the top level, but that's 'messy' on the namespace. A more proper solution to this problem is to define a compound-unit/sig:

> (define monty-python-and-the-holy-grail@
      (compound-unit/sig silly-movie^
        (import)
        (link (A : acting-troupe^ (actors))
              (B : silly-movie^ (movie@ A)))
        (export (open B))))

This new compound unit will invoke without objections:

> (define-values/invoke-unit/sig
     (monty-python and-the-holy-grail)
     monty-python-and-the-holy-grail@)

Note that we use the define-values variant to make sure that the symbols from movie@ are defined at the top level at the end of the invocation. There is another way to do things and that is to realize that a unit, signed or not, is a function and should return a value. Thus, changing our unit slightly:

> (define movie@
   (unit/sig silly-movie^
     (import acting-troupe^)

     (define (monty-python)
       (print graham-chapman)
       (print john-cleese)
       (print eric-idle)
       (print michael-palin))

     (define (and-the-holy-grail)
         (print 'coconuts)
         (print 'boring-historian)
         (print 'bring-out-your-dead)
         (print 'scene-24)
         (print 'and-so-on))

     and-the-holy-grail))

Doing things this way, we can control whether or not and what the symbol for and-the-holy-grail is at the top level. Now calling invoke-unit/sig will return a <#procedure> instead of void, which you can bind or immediately apply.

Discussion

Take note that this only describes the basic features of signed units, and that there is considerably more functionality embedded in unitsig.ss. From here you can begin coding component software with an understanding of what a unit is, what a signature is, and why to bother with a compound-unit. After having read this tutorial, you should be able to gradually add the more esoteric functionality of unit/sig to your repertoire by reading the MzLib? documentation and experimenting with the functions within.


Comments about this recipe

Contributors

-- JeffHeard - 18 Aug 2006

CookbookForm
TopicType: Recipe
ParentTopic: GettingStartedRecipes
TopicOrder: 999

 
 
Copyright © 2004 by the contributing authors. All material on the Schematics Cookbook web site is the property of the contributing authors.
The copyright for certain compilations of material taken from this website is held by the SchematicsEditorsGroup - see ContributorAgreement & LGPL.
Other than such compilations, this material can be redistributed and/or modified under the terms of the GNU Lesser General Public License (LGPL), version 2.1, as published by the Free Software Foundation.
Ideas, requests, problems regarding Schematics Cookbook? Send feedback.
/ You are Main.guest