common lisp:宏如何使用以编程方式生成的名称定义其他方法/宏?

发布于 2024-11-04 23:45:59 字数 1073 浏览 4 评论 0原文

我意识到我的代码的某个部分由看起来相似的方法组组成(就像我有多个三重奏:一个由程序员的其他两个函数调用的辅助函数)。我正在尝试编写一个宏来为我定义这三个函数,以便我所需要做的就是调用该宏。但我的尝试导致 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))

另外,在我学习如何让它工作之后,如果我让这个宏定义其他宏而不是其他函数,是否还会有任何额外的问题?我读了如何编写宏定义common 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!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

薯片软お妹 2024-11-11 23:45:59

试试这个:
<代码>

(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) )))

对原始定义进行了以下更改 - 第一个更改是关键的更改:

  1. 使用 (intern ... package) 将每个计算符号名称插入到与基本名称相同的包中。
  2. 引入了变量package,它绑定到所提供的base-name符号的包。
  3. let 更改为 let*,以允许新引入的变量 package 在后续变量中引用。
  4. 将辅助方法的前缀更改为大写,以匹配普通 Lisp 符号的约定。

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:

  1. Interned each of computed symbol names into the same package as the base name using (intern ... package).
  2. Introduced the variable package which is bound to the package of the supplied base-name symbol.
  3. Changed let to let* to allow the newly introduced variable package to be referenced in subsequent variables.
  4. Changed the prefix of the helper method to upper case to match the convention for normal Lisp symbols.
戈亓 2024-11-11 23:45:59

使用INTERN来转动将函数名称字符串生成为符号。

Use INTERN to turn the generated function name strings into symbols.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文