gpt4 book ai didi

function - 使用不同的表达式系统地调用 Common Lisp 宏

转载 作者:行者123 更新时间:2023-12-02 17:57:45 25 4
gpt4 key购买 nike

我正在学习 Common Lisp (SBCL)。
我想创建一个工具来调用两个(或更多)宏,其中包含几个仅在某些参数上有所不同的相似表达式。

我想定义表达式的基数,然后使用我提供的参数对其进行修改。为此,我想到了 lambda 函数定义。

据我所知,宏没有与 funcall 类似的东西,因此我还将宏封装在 lambda 中。

我觉得我对所有这些 lambda 和 funcall 感到过于复杂。有没有更优雅的方式?

这些宏来自外部库,所以我不想修改它们。
(具体来说, Fiveam 测试库的完成信号。)

这里是一个示例代码:

(defmacro macro1 (body) ())
(defmacro macro2 (body) ())

(defun check-expr-with-args (do-m func args)
(dolist (arg args)
(format t "~a " arg)
(funcall do-m (lambda () (funcall func arg)))))

(let ((test-expr
#'(lambda (val) (format t "~a" val)))
(cases (list
(list #'(lambda (func) ( macro1 (funcall func)))
(list 1 2 3 4 5))
(list #'(lambda (func) ( macro2 (funcall func)))
(list -4 -5 -6 -7 -8 -9)))))
(dolist (c cases)
(check-expr-with-args (first c) test-expr (second c))))

最初,我尝试将宏名称传递给我的 check-expr-with-args 函数,并以引用形式传递表达式,依赖于参数插入的词法作用域。但这并没有成功。

最佳答案

我认为您可以编写一个包装宏来生成调用 macro1 的代码(和macro2)。例如,我在这里定义 m1它采用 (i) 一个测试表达式和 (ii) 一个预计在运行时计算为值列表的表达式。

(defmacro m1 (test-expr input-expr)
(let ((arg (gensym)))
`(dolist (,arg ,input-expr)
(macro1 ,test-expr ,arg))))

两者test-exprinput-expr被注入(inject) dolist表达式,它绑定(bind)一个名为 arg 的变量。这里arg是一个新的符号,由 gensym 引入,以避免意外隐藏 test-expr 中可能使用的变量或符号宏.

例如:

(m1 (some-test-p) (list 1 2 3 4))

上面的内容展开为:

(DOLIST (#:G1909 (LIST 1 2 3 4)) 
(MACRO1 (SOME-TEST-P) #:G1909))

结果表达式包含MACRO1 ,也将得到扩展。但它现在被包装在一个表达式中,该表达式迭代在运行时计算的某些列表。在这里,它是一个常量,但您可以将其替换为任何其他表达式。

总之,通常最好通过将您自己的宏扩展到其他宏来在宏级别组合宏。

关于function - 使用不同的表达式系统地调用 Common Lisp 宏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75270985/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com