I am putting together a macro to generate simple functions of the style:
(defun hello ()
(format t "hello~&"))
Each new function will have hello replaced.
(defmacro generate-echoers (list)
`(let ((list-of-functions
(loop for var in ,list
collect
`(defun ,(intern var) ()
(format t ,(concatenate var "~&"))))))
`(progn
,list-of-functions)))
I developed the above function, which demonstrates conclusively that I have not yet masted quote-times and phases of expansion.
The desired usage is as follows: (generate-echoers '("hi" "ping" "pong")) => ;A list of functions that each say their name, as HELLO does above.
A function to generate:
(defun hello ()
(format t "hello~&"))
I would first write a function which creates above code:
(defun make-echoers (name)
`(defun ,(intern (string-upcase name)) ()
(format t ,(concatenate 'string name "~&"))))
Note that symbols are by default uppercase in Common Lisp - so we are using uppercase, too.
Then you can test it:
CL-USER 1 > (make-echoers "hello")
(DEFUN HELLO NIL (FORMAT T "hello~&"))
Works. Now let's use it:
(defmacro generate-echoers (list)
`(progn ,@(mapcar #'make-echoers list)))
Test it:
CL-USER 2 > (macroexpand-1 '(generate-echoers ("hi" "ping" "pong")))
(PROGN
(DEFUN HI NIL (FORMAT T "hi~&"))
(DEFUN PING NIL (FORMAT T "ping~&"))
(DEFUN PONG NIL (FORMAT T "pong~&")))
Your code can be simplified and made more correct like this:
(defmacro generate-echoers (list)
`(progn ,@(loop :for var :in list
:collect `(defun ,(intern (format nil "~:@(~A~)" var)) ()
(format t ,(concatenate 'string var "~&"))))))
First of all, you've got to splice the loop's result into the generated body.
Also you've forgotten, that concatenate takes type parameter and to upcase all your vars (otherwise you'll get function names like |foo|).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With