如何使用Scheme定义语法宏增加记录字段

克拉塔克

给定一个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的incfdecf

(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] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何增加mongodb中的字段?

来自分类Dev

如何使用Jackson定义可选的JSON字段

来自分类Dev

如何在f#中将记录字段定义为数组?

来自分类Dev

如何使用涂鸦记录语法?

来自分类Dev

定义宏以改善特定功能的语法

来自分类Dev

vim语法:如何使用包含的字段

来自分类Dev

在Scheme中定义宏以创建花式子列表

来自分类Dev

如何定义与结构数组C一起使用的宏

来自分类Dev

如何在Yesod-Persistent中使用记录语法

来自分类Dev

如何使用宏本身的信息来重新定义C ++ #define宏?

来自分类Dev

Elixir:如何使用列表作为变量来定义多个宏?

来自分类Dev

如何在Qt中使用宏定义信号

来自分类Dev

如何在Chicken Scheme中使用宏扩展程序中的现有宏(例如`let-values')?

来自分类Dev

如何在Haskell中使用记录语法为类型定义`bind`?

来自分类Dev

C宏函数定义语法问题

来自分类Dev

在SAS中使用宏时的语法问题

来自分类Dev

如何定义使用另一个宏的C宏?

来自分类Dev

如何增加输入字段的值?

来自分类Dev

使用Hygenic宏展平语法树

来自分类Dev

Scheme宏中的语法引用

来自分类Dev

如何扩展`Classname / staticField`宏语法

来自分类Dev

SQL-如何为返回的每10条记录将结果集中的字段增加1

来自分类Dev

如何使用NOT语法获取记录?

来自分类Dev

如何在OperationOutcome的位置字段上对JSON使用XPath语法?

来自分类Dev

使用宏的INDEX公式的语法错误

来自分类Dev

Elixir:如何使用列表作为变量来定义多个宏?

来自分类Dev

如何记录键盘宏?

来自分类Dev

如何使用 VSTS 发布任务在 IIS 上添加自定义高级日志记录字段

来自分类Dev

使用宏定义结构和函数,如何停止多个定义

Related 相关文章

热门标签

归档