[pro] The Best Examples of "Code is Data"
Ram Krishnan
kriyative at gmail.com
Mon Sep 6 17:18:18 UTC 2010
On Sun, Sep 5, 2010 at 5:24 AM, Kazimir Majorinc <kazimir at 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) , at body)))))
(cond
((null clauses) `(progn , at 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) , at body)))
(t
(cons-form 'destructuring-bind (caar clauses) clauses body))))
(t
`(let (,(car clauses))
(bind ,(cdr clauses) , at body))))))
----------------
Cheers,
-ram
More information about the pro
mailing list