gpt4 book ai didi

macros - 在运行时处理内部变量和数据结构的 LISP 宏

转载 作者:太空宇宙 更新时间:2023-11-03 18:58:14 25 4
gpt4 key购买 nike

我有用 JavaScript 编写的 LISP(https://jcubic.github.io/lips/ 以及您可以尝试的在线演示)并且我有这样的宏:

(define-macro (globalize symbol)
(let ((obj (--> (. lips 'env) (get symbol))))
`(begin
,@(map (lambda (key)
(print (concat key " " (function? (. obj key))))
(if (function? (. obj key))
(let* ((fname (gensym))
(args (gensym))
(code `(define (,(string->symbol key) . ,args)
(apply (. ,obj ,key) ,args))))
(print code)
code)))
;; native Object.key function call on input object
(array->list (--> Object (keys obj)))))))

在这段代码中我使用了这个:

(let ((obj (--> (. lips 'env) (get symbol))))

我使用以下方法调用这个宏:

(globalize pfs)

为 pfs 的每个静态方法创建函数(它是来自 isomorphic-git 的 LightingFS,其中每个函数返回一个 promise,就像来自节点的 fs)。

但它不适用于这样的事情:

(let ((x pfs))
(globalize x))

因为 lips.env 是全局环境。

所以我的问题是宏应该如何工作?他们是否应该只将输入数据作为符号处理,以便在 lisp 代码评估之前永远无法访问对象?

根据变量生成一堆函数的 LISP 宏应该是什么样子的。例如在方案中,如果我在变量中有一个列表,并且想为每个将返回一个值的键生成函数:

输入:

(define input `((foo . 10) (bar . 20)))

输出:

(begin
(define (foo) 10)
(define (bar) 20))

如果我使用(macro input),我能写出这样的输出的宏吗?或者唯一的选择是 (macro ((foo . 10) (bar . 20)))?

我可以接受通用 Scheme 或 Common LISP 答案,但请不要从 scheme 发布定义语法和卫生宏,我的 lisp 没有而且永远不会有。

问题似乎是我想在宏扩展时访问值,并且它需要具有运行时的值。第二个问题在这种情况下,eval 是唯一的选择吗?

这适用于 biwascheme :

(define-macro (macro obj)
(let ((obj (eval obj)))
`(begin
,@(map (lambda (pair)
(let ((name (car pair))
(value (cdr pair)))
`(define (,name) ,value)))
obj))))

(define input `((foo . 10) (bar . 20)))

(macro input)

(foo)
;; ==> 10
(bar)
;; ==> 20

(在我的 lisp eval 中不像在 biwascheme 中那样工作,但那是另一个问题)。

但这行不通,因为 x 不是全局的:

(let ((x '((g . 10)))) (macro x))

带有 eval 的宏是您通常会做的事情,还是应该避免使用它们?有没有其他方法可以根据运行时对象生成一堆函数。

最佳答案

在 Common Lisp 中:在运行时创建和编译函数。

CL-USER 20 > (defparameter *input* '((foo . 10) (bar . 20)))
*INPUT*

CL-USER 21 > (defun make-my-functions (input)
(loop for (symbol . number) in input
do (compile symbol `(lambda () ,number))))
MAKE-MY-FUNCTIONS

CL-USER 22 > (make-my-functions *input*)
NIL

CL-USER 23 > (foo)
10

CL-USER 24 > (bar)
20

来自局部变量:

CL-USER 25 > (let ((input '((foo2 . 102) (bar3 . 303))))
(make-my-functions input))
NIL

CL-USER 26 > (bar3)
303

用宏,比较笨拙和受限:

CL-USER 37 > (defparameter *input* '((foo1 . 101) (bar2 . 202)))
*INPUT*

CL-USER 38 > (defmacro def-my-functions (input &optional getter)
`(progn
,@(loop for (symbol . number) in (if getter
(funcall getter input)
input)
collect `(defun ,symbol () ,number))))
DEF-MY-FUNCTIONS

CL-USER 39 > (def-my-functions *input* symbol-value)
BAR2

CL-USER 40 > (foo1)
101

关于macros - 在运行时处理内部变量和数据结构的 LISP 宏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55857349/

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