Misc-Extensions
A convenience library containing a motley collection of macros and other extensions.

Misc-Extensions is intended as a catchall for small, general-purpose extensions to Common Lisp, typically macros. It is in the public domain. It currently contains the following:

  • A replacement for let that makes it much easier to write CL in a functional style making heavy use of multiple values. It generalizes the semantics of let, let*, and multiple-value-bind. For example:

    (let ((a b c (foo x))
          ((d (bar a b))
           (e (baz b c)))
          (f (zot)))
      ...)
    

    This binds a, b, and c to the three values of (foo x), and, in parallel, binds f to the value of (zot); then it binds d and e. The nesting level indicates scoping, so the values of a, b, and c are in scope for the clauses binding d and e, but not for the clause binding f. All these bindings are in scope for the body.

  • A replacement for cond that deals with the occasional situation where one wants to refer to a value in the body of a cond clause that was computed in the predicate. If the car of the predicate is the symbol let, then the scope of the bindings established by that let is extended to include the entire clause. Example:

    (cond ((let ((x y (foo q)))
             x)
           (bar y))
          ...)
    

  • Yet another iteration macro called GMap, which generalizes mapcar by providing an extensible set of sequence generators and allowing an arbitrary function to combine the results. GMap is in much the same spirit as Dick Waters' Series package; it provides much of the useful functionality of Series, but with a far simpler implementation. Some examples:

    * (gmap :list #'+ (:list '(1 2 3)) (:index 10 nil))
    (11 13 15)
    * (gmap :string #'code-char (:index #x40 #x45))
    "@ABCD"
    * (gmap (:values :list :vector) (lambda (x y) (values (+ x y) (* x y)))
    	(:vector #(0 12 42 17)) (:index 6 nil))
    (6 19 50 26)
    #(0 84 336 153)
    * (gmap :alist nil (:plist '(a 1 b 2 c 3)))
    ((A . 1) (B . 2) (C . 3))
    * (gmap :plist nil (:alist '((x . 0) (y . 1) (z . 2))))
    (X 0 Y 1 Z 2)