Common Lisp Extension: DEFINER
 

DEFINER

The DEFINER library contains an extension to Common Lisp that allows programmer to nicely reuse some common "definition" idioms.

Many CL packages extend the language by adding a slew of

  (defsomething ...)
  
and/or
  (define-something-else ...)
  
macros. Well, wouldn't it be nice to have a more controlled way to do that? DEFINER is for you. A quick hack where we extend CL to define more complex definition forms.

The idea is to provide a general macro def and a specialized generic function for further extensions.

The end result is to make Common Lisp definitions look like Python. Of course, with a twist. def is written completely in Common Lisp, and in Python you need to hack the parser to extend the behavior of def.

Examples

Functions, macros, and methods

Basic definition forms for functions, methods and macros.

Now you say:

  (def function foo (x)
    (+ x 42))
  
and
  (def macro foo (y)
    `(list ,y 42))
  
and
  (def generic bar (x)
    (:method ((x string)) ...))
  
and
  (def method bar :before ((x symbol)) ...)
  

Variables, parameters, and constants

The pattern is the same.

  (def var *x*)
  
and
  (def parameter *foo* 42)
  
and
  (def constant +bar+ "bar")
  

Classes

To define classes now you say:

  (def class reptilian (animal) ...)
  

Structures

There is a very straighforward rendering of structures using the def macro. But it is much more fun to make the def form for structures behave like the def form for classes.

Now you say:

  (def structure foo
    (a
     (s 42 :type number))
    (:documentation "Foo structure.")
    (:print-function print-foo))
  
(Of course, nothing forbids us from reverting this to the straightforward rendering; we need to vote on this.)

Conditions

You know the drill...

  (def condition my-error (simple-error) ...)
  

Packages

Same story...

  (def package :foo (:use "CL")
    (:export "BAR"))
  

Types

Who says CL does not have types? Check out

  (def type forty-two ()
    '(member 42))
  
and
  (def type buffer (x)
    `(vector character ,x))
  

Defining "definers"

Any self-respecting CL hackers will never be satisfied with just defining a few macros. The self-respecting CL hacker wants to show off. So, the def macro accepts a special keyword, definer, that allows you to bend the thing unto itself.

The syntax of this definer form is

  (def definer for-what (&key type-of-naming-form name body-name) forms)
  

Example

As an example, consider how we could have defined (as we did) the definer for deftype:

  (def definer type (:name type-name)
    `(deftype ,type-name ,@definition-forms))
  
An explanation of this definition can be found in the description of the DEF macro.

Interesting things

So, how do you use this?

Suppose you were writing UFFI code. You would probably make use of the UFFI uffi:def-foreign-type macro to write things like

  (uffi:def-foreign-type char-ptr (* :char))
  

By using the definer facility you could now write

  (def uffi:foreign-type char-ptr (* :char))
  
It may not look much, but it seems more pleasant to the author and it has some nice side effects, e.g., for editors and IDEs writers.

How does it work?

The "DEF" package ("DEF" is a nickname) exports two main symbols (plus a few more representing tags and local variables):

  • build-definition-form, a generic function.
  • def, the main macro.

def is the main macro used in "extended" code, while build-definition-form is used to extend the definition capabilities of your environment.

DEFINER Dictionary

Conclusions

All in all DEFINER is just a cute hack, but it has some niceties of its own. Moreover, it makes it possible to homogeneize a natural programming practice followed by several CL programmers.

Enjoy!


Questions? Queries? Suggestions? Comments? Please direct them at me.