给定一个Chez Scheme记录,其中包含许多数值字段,这些数值字段通常会以较小的增量和减量(通常是一个数值)不断地进行突变,那么有没有一种方法可以编写一个可以通过将字段值传递给字段值来对其进行更改的宏?我现在完成此操作的方式类似于以下REPL脚本:
Chez Scheme Version 9.5.4
Copyright 1984-2020 Cisco Systems, Inc.
> (define-record-type r (fields (mutable x) (mutable y)
;; and so on...
))
> (define my-r (make-r 3 5
;; and so on...
))
> (r-x-set! my-r (+ (r-x my-r) 1))
> my-r
#[#{r gak6l6ll8wuv7yd61kiomgudo-2} 4 5]
最好有一个简单的宏,比如说inc!
,它可以对记录中的字段进行增量/减量操作。我开始有点像计划版本的Lisp的incf
和decf
,
(define-syntax inc!
(syntax-rules ()
((_ x) (begin (set! x (+ x 1)) x))))
(inc! (r-x my-r)) ;; Syntax error
它适用于“普通”变量(并使易于实现dec!
),但是r-x-set!
在这种情况下,它不使用该机制来设置可变的记录字段。
有没有明显的方法可以编写这样的宏?您可以在其中传递对记录字段的引用而不必为每个字段写不同的内容吗?
您可以-set!
从给定的访问器构造一个转换器。这可以通过将访问器的符号转换为字符串并附"-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 5 7]
> (inc! (r-x my-r))
> my-r
#[#{r n5an6pxs3wvid36v2gvn8z9zo-5} 4 5 7]
> (dec! (r-z my-r))
> my-r
#[#{r n5an6pxs3wvid36v2gvn8z9zo-5} 4 5 6]
> (inc! (r-x my-r) (r-y my-r) (r-z my-r))
> my-r
#[#{r n5an6pxs3wvid36v2gvn8z9zo-5} 5 6 7]
eval
在increment-n!
宏观构造已经被绑定到突变的过程的象征。然后可以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
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句