common-idioms is a set of utilities that Brian Mastenbrook uses frequently during his development. As of version 3, it provides the following functions/macros:

  • AIF, anaphoric if which binds a macro SETF-IT during the execution of the ELSE clause.
  • AIF2, anaphoric if which tests on the second return value of the TEST (but binds IT and SETF-IT as AIF does).
  • DESTRUCTURING-CASE, a mega-macro for testing different ways to destructure a list, including literal matching and a GO tag to continue with the next possible destructuring lambda list.
  • EXPAND-ONLY, unportable Common Lisp which works in several implementations to expand all occurrences of the given macros in the supplied expression.
  • FCONSTANTLY, like CONSTANTLY for functions. (FCONSTANTLY #'GENSYM) is useful as an argument to MAPCAR.
  • MACROEXPAND-N, recursively MACROEXPAND-1 an expression N times. (Useful for heavy macrology.)
  • MAP1, like MAPCAR but with extra arguments to the supplied function. (MAP1 #'CONS LIST (GENSYM)) will make an alist of gensyms from the supplied list.
  • REDUCEN, multiple value aggregating REDUCE. Very useful for heavier uses of REDUCE, where you would ordinarily aggregate a list.
  • RUN-TESTS, a simple macro to run the supplied functions with no arguments, printing and collecting the results.
  • WITH-GENSYMS, everyone's favorite macro for binding symbols to identifiers in a body.

New in version 2 are the following:

  • SYMBOLIC, a macro which is used to create symbolic operations (like anaphoric operations, but with IT bound to a symbol-macro expanding to the argument)
  • SIF, a symbolic IF macro which binds IT to a symbol macro expanding to the TEST form
  • LET-ENV, a macro that allows you to play games with lexical scope by naming an environment, and calling it as if it were a macro to de-shadow chosen variables to their bindings at the point of environment capture.

This last one in particular needs some explanation:

(let ((x 1)
      (y 2))
  (let-env env
            (let ((x 3)
                  (y 4))
              (setf x 5)
              (env (x)
                   (setf x 6)
                   (setf y 7))
              (list x y)) (list x y)))) => (5 7 6 2)

This macro is unfortunately not totally portable as it currently depends on the order of macro expansion; however, if there is a way to make it portable, I'd be interested.

The grossly unportable EXPAND-ONLY function has been updated as well; it now can take an argument of T to mean "show all macro expansions", and any expansions encountered that don't appear to be present in the form or any of its recursive expansions will be returned the second value as an association list. (This is often useful with SETF, which can transform back and forth to SETQ.)

New in version 3 are the following:

  • LET-ENV*, like LET-ENV but the list of captures is supplied at the LET-ENV* site.
  • MACROLET*, a MACROLET with an implicit LET-ENV*

There is Albert-generated documentation available.