如何评估宏内兰伯达内部的形式?

发布于 2025-01-30 06:06:40 字数 682 浏览 1 评论 0原文

我在以下宏方面有问题:

(defmacro gather-params (&rest body)
  "Return plist of params"
  `(concatenate 'list
        (map 'list
             #'(lambda (plist)
                 (if (typep (first plist) 'keyword)
                     (cons 'list plist)
                     plist))
             ',body)))

在宏内,我无法通过在其前面添加逗号来评估PLIST,例如:,当我这样做时,编译器会抱怨变量,PLIST不存在。

我对宏内的范围不了解吗?

当前结果:

input:  (gather-params (:mykey (+ 1 1)) (list 1 2 3))
result:   ((LIST :MYKEY (+ 1 1)) (LIST 1 2 3))

所需结果:

input:  (gather-params (:mykey (+ 1 1)) (list 1 2 3))
result:   ((LIST :MYKEY 2) (LIST 1 2 3))

I'm having problems with the following macro:

(defmacro gather-params (&rest body)
  "Return plist of params"
  `(concatenate 'list
        (map 'list
             #'(lambda (plist)
                 (if (typep (first plist) 'keyword)
                     (cons 'list plist)
                     plist))
             ',body)))

Within the macro, I can't make plist evaluate by adding a comma in front of it, e.g: ,plist when I do that, the compiler complains that the variable ,plist does not exist.

Is there something I'm not understand about the scope within a macro?

Current result:

input:  (gather-params (:mykey (+ 1 1)) (list 1 2 3))
result:   ((LIST :MYKEY (+ 1 1)) (LIST 1 2 3))

Desired result:

input:  (gather-params (:mykey (+ 1 1)) (list 1 2 3))
result:   ((LIST :MYKEY 2) (LIST 1 2 3))

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

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

发布评论

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

评论(1

倾`听者〃 2025-02-06 06:06:40

(condenate'list'(1 2 3))只是(copy -list'(1 2 3))

- >两者都评估(1 2 3)

宏生成代码。它有一个反引用的列表。此反调用列表是在宏扩展时间计算的 - >当宏扩展发生时,例如在汇编过程中。

生成的代码具有称为plist的参数的函数。此功能在运行时执行。它在宏扩展过程中不存在。因此,plist在宏观扩展过程中没有变量。因此,您无法在宏观上的plist的值计算,因为那时该变量不存在。

如果要评估代码,则Common LISP为此具有函数eval。例如,可以在运行时调用eval

CL-USER 31 > (defmacro gather-params (&rest body)
              "Return plist of params"
              `(map 'list
                    #'(lambda (plist)
                        (if (typep (first plist) 'keyword)
                            (list 'list
                                  (first plist)
                                  (eval (second plist)))
                            plist))
                    ',body))
GATHER-PARAMS

CL-USER 32 > (gather-params (:mykey (+ 1 1)) (list 1 2 3))
((LIST :MYKEY 2) (LIST 1 2 3))

使用不同的方法查看此示例:

CL-USER 42 > (defmacro gather-params (&rest body)
               "Return plist of params"
               `(list ,@(mapcar
                         (lambda (plist)
                           (if (typep (first plist) 'keyword)
                               (list 'list
                                     ''list
                                     (first plist)
                                     (second plist))
                             plist))
                         body)))
GATHER-PARAMS

CL-USER 43 > (let ((foo 1))
               (gather-params (:mykey (+ foo foo)) (list 1 2 3)))
((LIST :MYKEY 2) (1 2 3))

(concatenate 'list '(1 2 3)) is just (copy-list '(1 2 3))

-> which both evaluate to (1 2 3).

The macro generates code. It has a backquoted list. This backquoted list is computed at macroexpansion time -> when the macro expansion happens, for example during compilation.

The generated code has a function with a parameter called plist. This function executes at runtime. It does not exist during macroexpansion. Thus plist is no variable during macroexpansion. Thus you can't compute a value of plist during macroexpansion, since the variable does not exist then.

If you want to evaluate code, then Common Lisp has the function eval for that. One can for example call eval at runtime.

CL-USER 31 > (defmacro gather-params (&rest body)
              "Return plist of params"
              `(map 'list
                    #'(lambda (plist)
                        (if (typep (first plist) 'keyword)
                            (list 'list
                                  (first plist)
                                  (eval (second plist)))
                            plist))
                    ',body))
GATHER-PARAMS

CL-USER 32 > (gather-params (:mykey (+ 1 1)) (list 1 2 3))
((LIST :MYKEY 2) (LIST 1 2 3))

Check out this example, with a different approach:

CL-USER 42 > (defmacro gather-params (&rest body)
               "Return plist of params"
               `(list ,@(mapcar
                         (lambda (plist)
                           (if (typep (first plist) 'keyword)
                               (list 'list
                                     ''list
                                     (first plist)
                                     (second plist))
                             plist))
                         body)))
GATHER-PARAMS

CL-USER 43 > (let ((foo 1))
               (gather-params (:mykey (+ foo foo)) (list 1 2 3)))
((LIST :MYKEY 2) (1 2 3))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文