问题描述
我意识到我的代码的某些部分由看起来相似的方法组组成(就像我有多个三重奏:一个辅助函数,该辅助函数被其他两个供程序员使用的函数调用).我正在尝试编写一个宏,该宏将为我定义这三个函数,因此我需要做的就是调用该宏.但是,我的尝试导致了带有引号而不是生成的名称作为新符号的带引号的defun和函数调用.我在做什么错了?
示例(错误代码)
(defmacro def-trio (base-name)
(let
((helper-name (format nil "helper-~a" base-name))
(method-1 (format nil "~a-1" base-name))
(method-2 (format nil "~a-2" base-name)))
`(progn
(defun ,helper-name () 'helper-called)
(defun ,method-1 () (,helper-name) '1-called)
(defun ,method-2 () (,helper-name) '2-called))))
现在发生以下情况:
(def-trio my-trio)
==>
(PROGN (DEFUN "helper-MY-TRIO" () 'HELPER-CALLED)
(DEFUN "MY-TRIO-1" () ("helper-MY-TRIO") '1-CALLED)
(DEFUN "MY-TRIO-2" () ("helper-MY-TRIO") '2-CALLED))
此外,在我学会了如何使它工作之后,如果我让此宏定义其他宏而不是其他函数,是否还有其他问题?我阅读了如何编写宏定义常见Lisp中的宏,但我认为我的问题有所不同,因为我在询问以编程方式生成的符号/名称.我愿意接受纠正:)谢谢!
尝试一下:
对您的原始定义进行了以下更改-第一个更改是至关重要的:
- 使用
(intern ... package)
将每个计算出的符号名称与基本名称插入同一包中. - 引入了变量
package
,该变量已绑定到提供的base-name
符号的包中. - 将
let
更改为let*
,以允许在后续变量中引用新引入的变量package
. - 将helper方法的前缀更改为大写以匹配常规Lisp符号的约定.
I realized that a certain section of my code consists of groups of methods that look similar (like I have multiple trios: a helper function that gets called by two other functions meant for the programmer). I'm trying to write a macro that will define these three functions for me so that all I need to do is call the macro. But my attempt results in defuns and function calls that have quoted strings instead of the generated names as new symbols. What am I doing wrong?
Example (incorrect code)
(defmacro def-trio (base-name)
(let
((helper-name (format nil "helper-~a" base-name))
(method-1 (format nil "~a-1" base-name))
(method-2 (format nil "~a-2" base-name)))
`(progn
(defun ,helper-name () 'helper-called)
(defun ,method-1 () (,helper-name) '1-called)
(defun ,method-2 () (,helper-name) '2-called))))
Now the following happens:
(def-trio my-trio)
==>
(PROGN (DEFUN "helper-MY-TRIO" () 'HELPER-CALLED)
(DEFUN "MY-TRIO-1" () ("helper-MY-TRIO") '1-CALLED)
(DEFUN "MY-TRIO-2" () ("helper-MY-TRIO") '2-CALLED))
Also, after I learn how to get this working, are there any extra gotcha's if I had this macro define other macros instead of other functions? I read How do I write a macro-defining macro in common lisp but I think my question is a little different because I'm asking about programmatically generated symbols/names. I'm open to being corrected though :) Thanks!
Try this:
(defmacro def-trio (base-name) ; changes: (let* ; 3. ((package (symbol-package base-name)) ; 2. (helper-name (intern (format nil "HELPER-~a" base-name) package)) ; 1. 4. (method-1 (intern (format nil "~a-1" base-name) package)) ; 1. (method-2 (intern (format nil "~a-2" base-name) package)) ) ; 1. `(progn (defun ,helper-name () 'helper-called) (defun ,method-1 () (,helper-name) '1-called) (defun ,method-2 () (,helper-name) '2-called) )))
The following changes were made to your original definition -- the first change is the crucial one:
- Interned each of computed symbol names into the same package as the base name using
(intern ... package)
. - Introduced the variable
package
which is bound to the package of the suppliedbase-name
symbol. - Changed
let
tolet*
to allow the newly introduced variablepackage
to be referenced in subsequent variables. - Changed the prefix of the helper method to upper case to match the convention for normal Lisp symbols.
这篇关于常见的Lisp:宏如何使用程序生成的名称定义其他方法/宏?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!