首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将符号列表转换为要在宏中使用的标识符列表

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

Stack Overflow用户
提问于 2016-12-12 14:04:23
回答 1查看 468关注 0票数 3

考虑一下这样的场景,在这种情况下,我希望使用Racket宏指定一个非常简单的参与者语言。参与者是由定义实现某种逻辑的本地状态和消息处理程序的行为定义的。消息处理程序的主体既可以使用消息的形式参数,也可以使用状态变量。下面的代码实现了一个示例。

代码中有相当多的上下文,这可能甚至是不必要的。但是,为了提供一个运行中的示例,我已经将它包括进来了,而且我需要使用syntax-parametrize这一事实可能会使解决方案复杂化。特别感兴趣的是with-syntax宏中的MESSAGE子句,在这里,我要求(local-state-variable ...)模式匹配一个标识符列表,当前的#'local-state-variables是一个符号列表(由ACTOR宏中的syntax-parameterize绑定),因此不匹配。到目前为止,我还没有找到解决办法,尽管这似乎不应该是令人震惊的困难。我漏掉了什么明显的东西吗?

代码语言:javascript
复制
#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))))
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-12-12 16:32:15

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

代码语言:javascript
复制
;; 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))
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41102630

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档