gpt4 book ai didi

racket - 将符号列表转换为要在宏中使用的标识符列表

转载 作者:行者123 更新时间:2023-12-02 11:36:06 25 4
gpt4 key购买 nike

考虑这样的场景:我想使用 Racket 宏指定一种非常简单的 Actor 语言。参与者由定义一些本地状态和实现某些逻辑的消息处理程序的行为来定义。消息处理程序的主体可以使用消息的形式参数以及状态变量。下面的代码中实现了一个示例。

代码中有很多上下文,但可能根本没有必要。但是,我无论如何都将其包含在内,以便提供一个运行示例,并且事实上我需要使用 syntax-parametrize可能会使解决方案变得复杂。特别感兴趣的点是 with-syntax MESSAGE 中的条款宏,我需要 (local-state-variable ...)匹配标识符列表的模式,目前 #'local-state-variables这是一个符号列表(由 syntax-parameterize 宏中的 ACTOR 绑定(bind)),因此不匹配。到目前为止,我还没有找到解决方案,尽管它看起来并不那么困难。我错过了一些明显的东西吗?

#lang racket

(require (for-syntax syntax/parse))
(require racket/stxparam)

(define LOCAL_STATE
(lambda (stx)
(raise-syntax-error 'LOCAL_STATE "should only be used inside an actor" stx)))

; Define some syntax classes because abstractions are nice
(begin-for-syntax
(define-syntax-class actor-local-state
#:description "actor local state"
#:literals (LOCAL_STATE)
(pattern (LOCAL_STATE state-variable:id ...)))

(define-syntax-class message-pattern
#:description "actor message pattern"
(pattern (identifier:id argument:id ...))))


(define-syntax-parameter local-state-variables
(lambda (stx)
(raise-syntax-error 'local-state-variables "reserved keyword for actors" stx)))


(define-syntax (MESSAGE stx)
(syntax-parse stx
[(_ pattern:message-pattern body:expr ...+)
; Currently there is a "binding match failed" error on the following line, but replacing #'local-state-variables with #'(a b) (a list of identifiers) needless to say works.
(with-syntax ([(local-state-variable ...) #'local-state-variables])
; For simplicity just display the state variables - this is normally where some magic happens
#'(display '(local-state-variable ...)))]))


(define-syntax (ACTOR stx)
(syntax-parse stx
[(_ state:actor-local-state handler:expr ...+)
#'(syntax-parameterize
([local-state-variables '(state.state-variable ...)])
; For the sake of simplicity, an actor is currently a list of message handlers
(list handler ...))]))


; in this proof-of-concept code this should print (a b)
(define behaviour
(ACTOR (LOCAL_STATE a b)
(MESSAGE (add x y) (+ a b x y))))

最佳答案

使用syntax-parameter-value 。以下是使用语法参数来管理变量列表的示例:

;; vars : syntax parameter of (Listof Identifier)
(define-syntax-parameter vars null)

;; with-vars: like let, but set vars
(define-syntax (with-vars stx)
(syntax-parse stx
[(_ ([var:id rhs:expr] ...) . body)
#'(let ([var rhs] ...)
(syntax-parameterize ([vars (list (quote-syntax var) ...)])
. body))]))

;; get-vars: get vars (symbolic name) and their values
(define-syntax (get-vars stx)
(syntax-parse stx
[(_)
(with-syntax ([(var ...) (syntax-parameter-value #'vars)])
#'(list (list (quote var) var) ...))]))

;; Examples:

(get-vars)
;; => '()

(with-vars ([x 1])
(get-vars))
;; => '((x 1))

(with-vars ([x 1])
(with-vars ([y 2] [z 3])
(set! z 17)
(get-vars)))
;; => '((y 2) (z 17))

关于racket - 将符号列表转换为要在宏中使用的标识符列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41102630/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com