thorne <thorne@timbral.net> wrote:
+---------------
| Actually, as soon as i posted i thought of:
| (eval
| (cons 'progn
| (loop for x in foo collect
| (list 'deftag x))))
| Which seems to work, but something tells me it's not idiomatic
| code.... or is it?
+---------------
Nope. "EVAL bad." ;-}
I have no idea *why* you want to pollute your COMMON-LISP-USER package
namespace with a bunch of generated function names... but if you insist,
consider writing a macro which expands to the above code, e.g.:
(defmacro deftags (&rest tags)
`(progn
,(loop for tag in tags
collect `(deftag ,tag))))
A better, more idomatic way might be to create a *single* data
structure -- a hash table or an alist or a B-tree, whatever --
which maps your "tags" to anonymous functions which close over
the unique-per-function data they will need later. This can easily
be done without any macros at all!!
> (defvar *tagged-functions* (make-hash-table))
*TAGGED-FUNCTIONS*
> (defun add-tagged-function (tag)
(assert (symbolp tag) ()
"This version of the code works only with symbols, not ~s" tag)
(setf (gethash tag *tagged-functions*)
(lambda ()
(format t "Hi! My name is ~s~%" tag))))
ADD-TAGGED-FUNCTION
> (mapc #'add-tagged-function '(a b c d e f foo bar baz charlie mike))
(A B C D E F FOO BAR BAZ CHARLIE MIKE)
> (funcall (gethash 'charlie *tagged-functions*))
Hi! My name is CHARLIE
NIL
>
And you don't even need macros to make this convenient to use, e.g.:
> (defun do-tags (&rest rest)
;; Allow *either* a single list arg or a spread list of tags
(when (and (listp (first rest)) (endp (rest rest)))
(setf rest (first rest)))
(dolist (tag rest)
(funcall (gethash tag *tagged-functions*))))
DO-TAGS
> (do-tags 'foo)
Hi! My name is FOO
NIL
> (do-tags 'foo 'bar 'mike)
Hi! My name is FOO
Hi! My name is BAR
Hi! My name is MIKE
NIL
> (do-tags '(baz charlie d c))
Hi! My name is BAZ
Hi! My name is CHARLIE
Hi! My name is D
Hi! My name is C
NIL
> (mapc #'do-tags (append '(foo mike) '(a b)))
Hi! My name is FOO
Hi! My name is MIKE
Hi! My name is A
Hi! My name is B
(FOO MIKE A B)
>
-Rob
p.s. Exercise for the student: As it stands, this will fail:
> (add-tagged-function "gorp")
Error in function LISP::ASSERT-ERROR:
This version of the code works only with symbols, not "gorp"
[Condition of type SIMPLE-ERROR]
Restarts:
0: [CONTINUE] Retry assertion.
1: [ABORT ] Return to Top-Level.
...[etc.]...
Bonus question: Not only that, make it so that FOO, :FOO, "foo",
and "FOO" are all considered to be the "same" tag, regardless of
the current (READTABLE-CASE *READTABLE*).
-----
Rob Warnock <rpw3@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607