doc.txt

Macro Library

_Macro_ Library
===============

By Noel Welsh (noelwelsh at yahoo dot com)

Time-stamp: <05/10/28 11:05:18 nhw>

Keywords: _macro_, _aif_, _for_, _iteration_


Introduction
============

This library provides some useful macros.  Please
contribute additional macros to the library.

To use the whole library:

   (require (planet "macro.ss" ("schematics" "macro.plt" 1 0)))


_Anaphoric If_
==============

To use just these definitions:

   (require (planet "aif.ss" ("schematics" "macro.plt" 1 0)))

> (aif name [pred] expr true-arm false-arm)

The result of expr is bound to name in the scope of true-arm
and false-arm.  If (pred result) is not #f true-arm is
evaluated; otherwise false-arm is evaluated.  By default
the identity function is used for pred.

The _aif_ macro captures a common 3-step pattern:

  1. Evaluate an expression yielding a result v

  2. Test v for some condition

  3. Perform different actions on v depending on the result
     of the test.

Crucially the value v is used in the actions, so a simple if
statement will not suffice.  A common case occurs when
reading data from a port and checking for the end-of-file
condition.  For example

   (let ((result (read-line port)))
     (if (eof-object? result)
         (display "End reached")
         (display result)))

can be written using aif as:

   (aif result eof-object? (read-line port)
        (display "End reached")
        (display result)

This macro is based on one given in 'On Lisp' by Paul
Graham.


_Iteration_
==============

To use just these definitions:

   (require (planet "iteration.ss" ("schematics" "macro.plt" 1 0)))

> (for! (counter start stop) expr ...)

This is an imperative for loop.  Start and stop must evalute
to integers with stop greater than start.  Counter is bound
to each integer value between start (inclusive) and stop
(exclusive), and the expressions (expr ...) are executed for
their side effects.  The result is #void

Example:

  (for (i 0 4)
       (display i))

Prints

  0123


> (for ((counter start stop) (accum seed) ...) expr ...)

This is a functional for loop. Start and stop must evalute
to integers with stop greater than start.  Counter is bound
to each integer value between start (inclusive) and stop
(exclusive), and the accumulators are bound to the result of
evaluating the expressions.  The expressions should return
multiple values if there is more than one accumulator.

Example:

  (for ((i 0 4) (a -4) (b 0) (c 4))
       (values (add1 a)
               (add1 b)
               (add1 c)))

Evaluates to

  (values 0 4 8)