【发布时间】:2021-09-15 09:39:01
【问题描述】:
我正在 Racket 中创建一种 DSL(领域特定语言)。在这个 DSL 中,访问任何值都会导致它发生变异。换句话说,没有什么是纯粹的。我试图了解如何使用单个球拍宏定义几个新符号和宏,以尝试减少重复代码。该宏的一部分要求我引用私有/隐藏值。例如。当我引用a 时,它实际上是一个宏,它为私有值a_ 调用getter get-val(类似于普通lisp 中的符号宏)。我试图按照使用宏here 生成宏的文档进行操作,但它似乎并没有真正涵盖如何定义一个名为a_ 的符号给定一个名为a 的符号,因为它有点切线。虽然我不确定我正在寻找的功能是什么,但对 SO 的挖掘也没有给我带来太多帮助。
每个变量都使用相同的 getter 宏,它会在过程中改变值。这很好用。
(define-syntax-rule (get-val x)
(begin (set! x (not x)) x))
在原始代码中,我需要像这样为每个符号手动定义一个 getter 宏。这也可以正常工作,但会导致大量重复代码。
(define a_ #f)
(define-syntax (a stx) #'(get-val a_))
(define b_ #f)
(define-syntax (b stx) #'(get-val b_))
我更愿意定义一个看起来像这样的主宏。 (不工作)。我相信string->symbol 可能是问题所在。
(define-syntax-rule (def name val)
(begin
; Create new varname with name followed by underscore
; This should probably be a `let` ?
(define name_ (string-append name "_"))
; Assign the value to that (private) symbol.
(define (string->symbol name_) val)
; Create public getter macro
(define-syntax (name stx) #'(get-val (string->symbol name_)))))
然后我可以简单地创建很多这样的值
(def 'a #f)
(def 'b #f)
; or ideally this (not quoted)
(def a #f)
(def b #f)
一旦它工作正常,我还将创建一个 peek 宏,它允许我检查值而不会为了调试目的而改变,但一旦我知道如何创建第一个宏,我可能自己就能弄清楚。
【问题讨论】:
标签: dynamic macros lisp racket