I am creating a DSL (Domain specific language) in Racket. In this DSL accessing any value causes it to mutate. In other words, nothing is pure. I am trying to understand how to define several new symbols and macros using a single racket macro to try and reduce duplicated code. Part of this macro requires me to reference a private/hidden value. E.G. when I reference a
it is actually a macro which calls the getter get-val
for the private value a_
(Analogous to a symbol-macro in common lisp). I've tried to follow along with the documentation for generating macros with macros here but it doesn't really seem cover how to a define a symbol named a_
given one named a
because it's somewhat tangential. Digging through SO has also not led me to much, though I'm not sure what the functionality I'm looking for is called.
Each variable uses the same getter macro which mutates the value in the process. This works fine.
(define-syntax-rule (get-val x)
(begin (set! x (not x)) x))
In the original code I would need to manually define a getter macro for each symbol like this. This also works fine but leads to lots of duplicate code.
(define a_ #f)
(define-syntax (a stx) #'(get-val a_))
(define b_ #f)
(define-syntax (b stx) #'(get-val b_))
I would prefer to define a master macro once which looks something like this. (Not working). I believe that string->symbol
is likely the issue.
(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_)))))
Then I can simply create lots of values like this
(def 'a #f)
(def 'b #f)
; or ideally this (not quoted)
(def a #f)
(def b #f)
Once this is working I will also create a peek
macro which allows me to inspect the value without mutating for debugging purposes, though I can probably figure that out myself once I know how to create the first macro.