[Sbcl-help] Macro for defining functions

I have the following macro definition which takes a symbol as argument and
defines a new function. The symbol is used as the new function name:
(defmacro make-fn (fn-name)
`(defun ,fn-name ()
(format t "~a~%" ',fn-name)))
The macro seems to work correctly:
CL-USER> (make-fn my-function)
MY-FUNCTION
CL-USER> (my-function)
MY-FUNCTION
But when it is called from within the `dolist` macro a function with name
`fn-name` is defined:
(defparameter *fn-names* '(func01 func02))
(dolist (fn-name *fn-names*)
(make-fn fn-name))
CL-USER> (func01)
Error: FUNC02 is undefined.
CL-USER> (fn-name)
FN-NAME
What is wrong with the macro definition?
Thank you,
--Vijay

Thread view

I have the following macro definition which takes a symbol as argument and
defines a new function. The symbol is used as the new function name:
(defmacro make-fn (fn-name)
`(defun ,fn-name ()
(format t "~a~%" ',fn-name)))
The macro seems to work correctly:
CL-USER> (make-fn my-function)
MY-FUNCTION
CL-USER> (my-function)
MY-FUNCTION
But when it is called from within the `dolist` macro a function with name
`fn-name` is defined:
(defparameter *fn-names* '(func01 func02))
(dolist (fn-name *fn-names*)
(make-fn fn-name))
CL-USER> (func01)
Error: FUNC02 is undefined.
CL-USER> (fn-name)
FN-NAME
What is wrong with the macro definition?
Thank you,
--Vijay

>I have the following macro definition which takes a symbol as argument and
>defines a new function. The symbol is used as the new function name:
>
>(defmacro make-fn (fn-name)
> `(defun ,fn-name ()
> (format t "~a~%" ',fn-name)))
>
>The macro seems to work correctly:
>
>CL-USER> (make-fn my-function)
>MY-FUNCTION
>CL-USER> (my-function)
>MY-FUNCTION
>
>But when it is called from within the `dolist` macro a function with name
>`fn-name` is defined:
>
>(defparameter *fn-names* '(func01 func02))
>
>(dolist (fn-name *fn-names*)
> (make-fn fn-name))
>
>CL-USER> (func01)
>Error: FUNC02 is undefined.
>CL-USER> (fn-name)
>FN-NAME
>
>What is wrong with the macro definition?
I am not sure what you want is achievable with macros without changing
the calling code.
Macros get as their parameters literal unevaluated parts of code of
their invokation.
Macros get expanded in compile-time, before code is run.
So in your code the macro call doesn't know it is inside dolist and only
knows it is called as (make-fn fn-name). So it works just like in the
first example.
I would just write a second macro that generates a progn:
(defmacro make-fns (fn-names)
`(progn
,@(loop for fn-name in fn-names
collect `(make-fn ,fn-name))))
(make-fns (func-01 func-02))

Vijay Mathew <vijay.the.lisper@...> writes:
> I have the following macro definition which takes a symbol as argument
> and defines a new function. The symbol is used as the new function
> name:
>
> (defmacro make-fn (fn-name)
> `(defun ,fn-name ()
> (format t "~a~%" ',fn-name)))
>
> The macro seems to work correctly:
>
> CL-USER> (make-fn my-function)
> MY-FUNCTION
> CL-USER> (my-function)
> MY-FUNCTION
>
> But when it is called from within the `dolist` macro a function with
> name `fn-name` is defined:
>
> (defparameter *fn-names* '(func01 func02))
>
> (dolist (fn-name *fn-names*)
> (make-fn fn-name))
>
> CL-USER> (func01)
> Error: FUNC02 is undefined.
> CL-USER> (fn-name)
> FN-NAME
>
> What is wrong with the macro definition?
There's nothing wrong in the macro.
There's something wrong in your expectations.
Macros work at macroexpansion time (usually included at compilation
time). They don't have access to run-time data (run-time data may never
exist (if you don't run the program), or may exist in one thousand years
(if you only run it then), or may exist in trillion instances (if you
run it in a loop).
If you want to do something at run-time, then write a function:
(defun make-function (fname)
(setf (symbol-function fname) (lambda () (format t "~A~%" fname))))
(mapcar (function funcall) (mapcar (function make-function) '(func01 func02)))
prints:
func01
func02
--> (nil nil)
Notice how in the CLHS, operators named DEFsomething are usually
macros, while operators named MAKE-something are usually functions.
--
__Pascal Bourguignon__
http://www.informatimago.com/