opening it up with Common Lisp

Favorite weblogs

Lisp Related

Bill Clementson

Finding Lisp

Lemonodor

Lispmeister.com

Planet Lisp

Politics

Orcinus

Talking Points Memo

This Modern World

Working for Change

Other home

Polliblog

Recent Readings

Book review: Darwinia
Reviewed: Friday, August 11, 2006

Summer reading: Spin
Reviewed: Saturday, August 5, 2006

Runner
Reviewed: Tuesday, July 18, 2006

the Omnivoire's Delimma
Reviewed: Wednesday, July 12, 2006

the Golem's Eye
Reviewed: Wednesday, May 31, 2006





tinderbox
 width=

the Human Condition
Sunday, August 13, 2006

I like conditions. I like them a lot. I like to use them to describe bad program states instead of strings. (e.g., (assert (ok-p state) nil 'it-is-not-ok-condition :state state) instead of (assert (ok-p state) nil "It is not ok")). I like them because you can easily test whether or not they happened programmatically and because using them helps to centralize error messages -- and thus gives me hope that I can make them consistent. There is a catch though: define-condition is a prolix form. Thus Metatilities has long had defcondition to make writing them a bit easier and yesterday I wrote a sibling macro (with the same name) to handle my most common case. The macro is simplicity itself:

(defmacro defcondition (name (&rest super-conditions) 
			slot-specs format &body args)
  (flet ((massage-slot (slot-spec)
	   (cond ((atom slot-spec)
		  `(,slot-spec 
		    :initarg ,(read-from-string (format nil ":~a" slot-spec))))
		 (t
		  slot-spec)))
	 (massage-format-arg (arg)
	   (cond ((atom arg)
		  `(slot-value condition ',arg)) 
		 (t
		  arg))))
    `(progn
       (export '(,name))
       (define-condition ,name ,super-conditions
	 ,(mapcar #'massage-slot slot-specs)
	 (:report (lambda (condition stream)
		    (format stream ,format 
			    ,@(mapcar #'massage-format-arg args))))))))
  

and this lets us write

(define-condition record-number-too-large-error
    (invalid-record-number-error)
  ((record-count :initarg :record-count))
  (:report 
   (lambda (condition stream)
     (format stream 
	     "Record number ~a is too large for this store. Store size is ~a."
	     (slot-value condition 'record-number)
	     (slot-value condition 'record-count)))))

as

(defcondition record-number-too-large-error
    (invalid-record-number-error)
    (record-count)
    "Record number ~a is too large for this store. Store size is ~a."
  record-number record-count)

(the record-number slot is inherited). It's not much but its enough to make writing simple condition like this almost as easy as writing an error message as string. Programming environments are (in part) about reducing impedance and about making it easy to do the right thing.


|

Home | About | Quotes | Recent | Archives

Copyright -- Gary Warren King, 2004 - 2006