Macros 如何使用Scheme define syntax宏增加记录字段

Macros 如何使用Scheme define syntax宏增加记录字段,macros,scheme,chez-scheme,define-syntax,Macros,Scheme,Chez Scheme,Define Syntax,给定一个Chez Scheme记录,其中有许多数值字段不断地以小的增量和减量(通常是一个)进行变异,有没有办法编写一个宏,通过将字段值传递给字段来变异字段值?我现在完成这项工作的方式类似于以下REPL转录本: Chez方案9.5.4版 版权所有1984-2020思科系统公司。 >(定义记录类型r(字段(可变x)(可变y) 等等 )) >(定义my-r(制造-r 3 5 等等 )) >(r-x-set!my-r(+(r-x my-r)1)) >my-r #[r gak6ll8wuv7yd61kio

给定一个Chez Scheme记录,其中有许多数值字段不断地以小的增量和减量(通常是一个)进行变异,有没有办法编写一个宏,通过将字段值传递给字段来变异字段值?我现在完成这项工作的方式类似于以下REPL转录本:

Chez方案9.5.4版
版权所有1984-2020思科系统公司。
>(定义记录类型r(字段(可变x)(可变y)
等等
))
>(定义my-r(制造-r 3 5
等等
))
>(r-x-set!my-r(+(r-x my-r)1))
>my-r
#[r gak6ll8wuv7yd61kiomgudo-2}4 5]
如果有一个简单的宏就好了,比如说
inc,它可以对记录中的字段执行变异递增/递减操作。我从Lisps的Scheme版本
incf
decf
开始

(定义语法公司!
(语法规则()
((x)(开始(set!x(+x1))x)))
(inc!(r-x my-r));;语法错误
它适用于“普通”变量(并且易于实现
dec!
),但它不使用该机制来设置可变记录字段
r-x-set在这种情况下


有没有一种明显的方法来编写这样一个宏?一种只需传递对记录字段的引用而不必为每个字段编写不同内容的方法?

您可以构造一个
-集给定访问器中的mutator。这可以通过将访问器的符号转换为字符串并附加
“-set!”
来实现。然后可以使用
eval
获得实际的变异程序。下面是一个宏,它将指定字段的增量增加一定量
n

(define-syntax increment-n!
  (syntax-rules ()
    [(_ (acc rec) n)
     (let* ((acc-name (symbol->string (quote acc)))
            (mut-name (string-append acc-name "-set!"))
            (mut! (eval (string->symbol mut-name))))
       (mut! rec (+ (acc rec) n)))]))
这可用于创建
inc宏:

(define-syntax inc!
  (syntax-rules ()
    [(_ (acc rec)) (increment-n! (acc rec) 1)]))
但是,如果能够同时增加多个字段,那就太好了;这里是
inc
dec执行此操作的宏:

(define-syntax inc!
  (syntax-rules ()
    [(_ (acc rec) ...) (begin (increment-n! (acc rec) 1) ...)]))

(define-syntax dec!
  (syntax-rules ()
    [(_ (acc rec) ...) (begin (increment-n! (acc rec) -1) ...)]))
样本交互:

>my-r
#[r n5an6pxs3wvid36v2gvn8z9zo-5}3]
>(inc!(r-x my-r))
>my-r
#[r n5an6pxs3wvid36v2gvn8z9zo-5}4]
>(十二月!(r-z我的r))
>my-r
#[r n5an6pxs3wvid36v2gvn8z9zo-5}4]
>(inc!(r-x my-r)(r-y my-r)(r-z my-r))
>my-r
#[r n5an6pxs3wvid36v2gvn8z9zo-5}5 6 7]

关于使用
eval
increment-n宏构造一个已经绑定到mutator过程的符号。然后该符号可以绑定到
mut
直接,但是当表达式
(mut!rec(+(acc rec)n))
被计算时,将引发异常,因为
mut现在计算为一个符号,例如,
r-x-set。我们想要
mut
在过程调用中计算过程。通过对构造的符号调用
eval
,我们首先得到绑定到该符号的mutator过程,将其绑定到
mut而不是符号

下面是一个REPL交互,说明了问题,希望有助于澄清:

> (define f (string->symbol "+"))
> f
+
> (f 1 2)

Exception: attempt to apply non-procedure +
Type (debug) to enter the debugger.
> (define f (eval (string->symbol "+")))
> f
#<procedure +>
> (f 1 2)
3
>(定义f(字符串->符号“+”)
>f
+
>(f 1 2)
异常:尝试应用非过程+
键入(debug)以进入调试器。
>(定义f(求值(字符串->符号“+”))
>f
#
>(f 1 2)
3.

谢谢。正是我想要的。而且很容易通过1以外的值扩展到inc/dec。如果您有时间,您能解释一下为什么在创建变异子时需要
eval
?我知道这个符号不是一个过程,但是
eval
如何解决这个问题呢?@clataq--我在回答的末尾添加了一些注释;如果你需要更多的澄清,请告诉我。这很有帮助。谢谢你的补充解释。