Making Your Own MzScheme Teachpacks

Tired of repeating your favorite handy helper functions or structures every time you start a new file? (For instance, list-visitors?) Here's how to collect them all into a teachpack, always accessible in drscheme via the language menu's "add teachpack..." item.

Below is a sample teachpack, which you can copy and modify to roll your own. Note that the teachpack's filename must agree with its name provided inside the file (up to the ".ss" suffix). So if you name this downloadable version something other than "teachpack-demo.ss", be sure to modify the file's contents to match.

(module teachpack-demo (lib "plt-pretty-big.ss" "lang")
  (provide 
     log-base   ; num, num --> num.    (log-base b x)
     length=1?  ; (list-of ANY) --> boolean
     )


  ;; log-base: num, num --> num
  ;; Return (log x), base b.
  ;; (Scheme's built-in "log" is natural-log.)
  ;; Note that the result is an inexact number.
  ;;
  (define (log-base b x) (/ (log x) (log b)))



  ;; length=1?:  (list-of ANY) --> boolean
  ;; 
  ;; This predicate is handy when dealing with non-empty-lists.
  ;;
  (define (length=1? lst)
    (begin
      ; First, check for correct type of input:
      (unless (list? lst) (raise-type-error 'length=1? "list" lst))
      (and (cons? lst) (empty? (rest lst)))))
  
  )


#| Dissecting the syntax:
  
  Roughly, the syntax for a module is:

    (module [module-name] (lib "htdp-advanced.ss" "lang")
       (provide [placeholders..]) 
       [body])

   We'll consider each part in turn.  
   This file has quite a bit of info; just scan it the first time or two.
  

  "module": keyword.

  "[module-name]", here "teachpack-demo": 
     the name of this teachpack; it can be anything.
     The teachpack's name must be the same as its filename (up to ".ss").


  "(lib ...)": This is the import language -- that is, what
     language-level the *module* is written in.
     Stick with the plt-pretty-big.
     (Note that other files which just *use* the teachpack
     can be in whatever language-level you want.)

     Aside:
     Be careful when using plt-pretty-big -- it is full scheme,
     and sometimes behaves differently than Advanced-student.
     For example, evaluating a "cond" where no clauses match
     is not an error -- the program continues merrily, returning (void)!

     Aside:
     (You might have wanted to instead use, say, 
         (lib "htdp-intermediate.ss" "lang")
     but there is a bug -- since htdp-intermediate doesn't recognize 
     the keyword "module", it won't understand its own teachpack.
     Hopefully this will be fixed in a future (post-v.202) release.)
     

  "provide": a keyword, which starts off a list
     of placeholders being exported from this teachpack.
     (So if you define a struct, which automagically defines
     several related placeholders for you, you can pick-and-choose which
     ones will be exported.)
     Warning: use only lower-case symbols & placeholders (see note under "pragmatics").

  "[body]", a sequence of statements and definitions
     Just like any other scheme file (though it's obligated to define all 
     the placeholders listed in the previous "provide" clause, of course).
     Anything defined but not listed in the "provide" clause is simply not exported
     (it is local to the module).
     Warning: use only lower-case symbols & placeholders (see note under "pragmatics").

     Aside:
     If you want to write a teachpack which needs another, different teachpack,
     you'll need to use "require", which is the in-program analog to the
     "add teachpack" menu item.  See helpdesk.
     (Since each teachpack specifies its own import language, they don't
     pay attention to what other teachpacks your program my have already added.
     That's a good thing -- else you might change my teachpack's behavior when you
     re-define placeholders which my teachpack uses.)

  
  Pragmatics:
  - There should not be any other code in the file except for
    the one "module".
  - Then were do you put your test cases?  Put them all
    in a separate file (living next to the teachpack, usually).
    Whenever you update your teachpack, be sure to re-run
    your test cases!
  - To get the teachpack, one can either use the "Add a teachpack..."
    menu item, or (if in full plt scheme) your program can contain 
    a "require" statement (see helpdesk).
  - Warning -- case-sensitivity -- 
    Within the teachpack, all identifiers and symbols may be auto-down-cased.
    To avoid confusion, *only* use lower case (exception: within string constants).
    (When reading teachpack files, mzscheme doesn't use your personal
     preferences for case-sensitivity, since teachpacks weren't necessarily
     written using your preferences!)


 If you have any questions (or, suggested clarifications) about this document,
 please contact ian@cs.rice.edu, thanks!
 See "how to use scheme" -- htus.org -- for further info
 on topics like reading from files, xml processing, cgi-scripts, etc.

 This teachpack-example can be reached via
    http://www.owlnet.rice.edu/~comp210/02fall/Handouts/teachpack-demo.shtml

 |#

Here is one more teachpack which usefully provides a way to write functions with optional arguments (using a macro; the example is not meant to be teach about macros in general, though).