# `def` A stupid project to dull the pain of using a few of CL's built-in `def*` forms. ## `def:var` Isn't it annoying that, if you want to leave a `defvar`-defined special variable uninitialized at the top-level, then you're not allowed to give that variable a docstring? Sure, you can always (setf (documentation *my-speical* 'variable) "oh good, docs") but that's irritating too. Enter `def:var` (def:var *oh-so-special* :doc "It's oh-so-special") Of course, you may still initialize the variable: (def:var *oh-so-special* :init (random 10) :doc "It's oh-so-special") ## `def:const` Even more obnoxious is the behavior of `defconst` whenever you `C-c C-c` in SLIME. You nearly always find yourself invoking a `CONTINUE` restart when, according to common sense, you should not have had to. Well no more! (def:const +its-ten+ 10 "It's just the number 10") If you re-evaluate that form, then nothing annoying happens. Of course, the form still expands out to `defconstant` so that a condition signals whenever you try to `setf` the name. ## `def:class` Admittedly, this one is less justfifed. There's already the extremely elaborate `defclass/std` in the `defclass-std` system available through quicklisp. But I think `defclass/std` is a little *too* thorough and ends up getting in its own way. The case for using a macro like this is that, well, most classes are defined in a very repetitive way. This macro just saves you some work: (def:class pt () (x y z :prefix :type real :initform 0) (uuid :ro :type integer :initform (make-uuid) :documentation "A unique ID") :documentation "A point in real 3d space") The above would expand out into (DEFCLASS PT NIL ((X :ACCESSOR PT-X :INITARG :X :TYPE REAL :INITFORM 0) (Y :ACCESSOR PT-Y :INITARG :Y :TYPE REAL :INITFORM 0) (Z :ACCESSOR PT-Z :INITARG :Z :TYPE REAL :INITFORM 0) (UUID :READER UUID :INITARG :UUID :TYPE INTEGER :INITFORM (MAKE-UUID) :DOCUMENTATION "A unique ID")) (:DOCUMENTATION "A point in real 3d space")) See `def:class`'s docstring for details. ## `def:fast` Common Lisp compilers like SBCL can produce extremely fast code ... if, that is, you help them out a little. Declaring types and `optimize` declare expressions can be a little verbose and irritating to add to every function that you want to be fast. `def:fast` lightens some of the typing load by embedding types inside the lambda list, and by declaring the return type of functions. E.g.: (defun list-of-fixnum-p (xs) (and (listp xs) (every #'sb-int:fixnump xs))) (deftype list-of-fixnum () '(satisfies list-of-fixnum-p)) (def:fast sum-fixnum ((x fixnum) (y fixnum) &rest (xs list-of-fixnum)) -> fixnum "Sums fixnums" (+ x y (reduce #'+ xs))) The above expands into (DEFUN SUM-FIXNUM (X Y &REST XS) "Sums fixnums" (DECLARE (TYPE LIST-OF-FIXNUM XS) (TYPE FIXNUM Y X) (VALUES FIXNUM) (OPTIMIZE (SPEED 3) (SAFETY 0))) (+ x y (REDUCE #'+ XS)))