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
- BUILD-DEFINITION-FORM.
- DEF, the main macro.
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.