On Sun, Sep 5, 2010 at 5:24 AM, Kazimir Majorinc <kazimir@chem.pmf.hr> wrote:
As first, good luck with this list!
I'm in search for best examples of "code is data" paradigm in Common Lisp. For most CL-ers, it probably means "macros", but eval, backquote, anything that processes the code as data is of interest. As "best" I think on the most surprising, powerful, sophisticated examples, not necessarily of a pedagogical value.
Imagine that someone invited you to write the presentation "Five best CL macros ... I seen" or "Five best CL macros ... I wrote." What would you chose and why?
Look forward to seeing more great macros from others on the list. Here's a macro I wrote called `bind' that I got a lot of utility from in a recent project. It was inspired by the `metabang-bind' facility (http://common-lisp.net/project/metabang-bind/), but with simpler and slightly different goals.
From the docstring:
This macro combines the behaviour of the forms `let*', `destructuring-bind', and `multiple-value-bind', permitting the following style of binding form: (bind (((:values m n) (values 10 20)) ((a b _c &key (d 10)) '(1 2 3)) (x 5)) (+ x a b d m n)) => 48 While Lisp purists may dislike it, I picked up the _foo notation for ignorable vars from Erlang, which can be handy at times. ---------------- (defmacro bind (clauses &body body) "This macro combines the behaviour of the forms `let*', `destructuring-bind', and `multiple-value-bind', permitting the following style of binding form: (bind (((:values m n) (values 10 20)) ((a b _c &key (d 10)) '(1 2 3)) (x 5)) (+ x a b d m n)) => 48 Note in the destructuring form (a b _c &key (d 10)), _c is a short form for declaring it as ignorable. This is a more limited and lightweight implementation of some ideas from metabang-bind (http://common-lisp.net/project/metabang-bind/)." (labels ((parse-arglist (args) (loop for arg in args collect arg into args when (and (symbolp arg) (eq (aref (symbol-name arg) 0) #\_)) collect arg into ignorables finally (return (values args ignorables)))) (cons-form (form args clauses body) (multiple-value-bind (arglist ignorables) (parse-arglist args) `(,form ,arglist ,@(cdar clauses) ,@(when ignorables `((declare ,(list* 'ignore ignorables)))) (bind ,(cdr clauses) ,@body))))) (cond ((null clauses) `(progn ,@body)) ((listp (caar clauses)) (cond ((eq (caaar clauses) :values) (cons-form 'multiple-value-bind (cdaar clauses) clauses body)) ((eq (caaar clauses) :slots) `(with-slots ,(cdaar clauses) ,@(cdar clauses) (bind ,(cdr clauses) ,@body))) (t (cons-form 'destructuring-bind (caar clauses) clauses body)))) (t `(let (,(car clauses)) (bind ,(cdr clauses) ,@body)))))) ---------------- Cheers, -ram