球拍数据->带无引号拼接的语法

问题描述 投票:0回答:1

在 Racket 中,我尝试使用 s-exp 来构建一种新语言。所以构建 if 语句的宏是:

(define-syntax (buildif stx)
  (syntax-case stx ()
    ;split the body (stx) and split into parts
    [(_ condition (then-expr ...) (else-expr ...))
     ;build the if statement
     #'(if condition
          (begin then-expr ...)
          (begin else-expr ...))]))

我遇到的问题是我想使用语法->数据或语法->列表将语法转换为数据来修改语法。但是,我无法使用取消引号拼接来转换 datum->syntax 来插入修改后的值。 我想应用一个宏,它接受一个基准列表并返回一个基准列表,使得 '((+ x y) (- x y)) 给出 '((- x y) (+ x y))。我想使用这个修改后的列表作为 if 语句的值

(define-syntax (rev-if stx) ;modified if
  (syntax-case stx ()
    [(_ condition (then-expr ...) (else-expr ...))
     ;convert the syntaxes to datums to manipulate
     (let ((con (syntax->datum #'condition))
           (newthen (opswap (syntax->list #'(then-expr ...))))
           (newelse (opswap (syntax->list #'(else-expr ...)))))
       ;I want to convert the datums back to syntax to execute
       (let ((composed `(if ,con (begin ,@newthen) (begin ,@newelse))))
         (datum->syntax #f composed)))])) 

如果我使用 datum->syntax 我会收到此错误: if:未绑定的标识符; 另外,没有 #%app 语法转换器绑定在: if

如果我尝试使用:

(syntax/loc stx ;build the syntax for the if
         (if ,con
             ;,@ unquote splicing to place syntax of datums into syntax
              (begin ,@newthen)
              (begin ,@newelse)))

我收到此错误: 取消引用:不在准引用中:(取消引用 con)

scheme racket
1个回答
0
投票

datum->syntax
的第一个参数告诉语法扩展器返回的语法应该具有的词法上下文(哪些标识符应该在范围内)。其传达方式是通过现有的语法对象;第一个参数的词法上下文被复制到返回值。

实现此目的的一种方法是在宏调用处使用词法上下文 (

k
)。

(define-syntax (rev-if stx) ;modified if
  (syntax-case stx ()
    [(k condition (then-expr ...) (else-expr ...))
     ;convert the syntaxes to datums to manipulate
     (let ((con (syntax->datum #'condition))
           (newthen (opswap (syntax->list #'(then-expr ...))))
           (newelse (opswap (syntax->list #'(else-expr ...)))))
       ;I want to convert the datums back to syntax to execute
       (let ((composed `(if ,con (begin ,@newthen) (begin ,@newelse))))
         (datum->syntax #'k composed)))]))

建议重写

(define-syntax (rev-if stx)
  (define (opswap stx)
    (syntax-case stx ()
      [(+ . t)
       (eq? (syntax->datum #'+) '+)
       #`(- . #,(opswap #'t))]
      [(- . t)
       (eq? (syntax->datum #'-) '-)
       #`(+ . #,(opswap #'t))]
      [(h . t)
       #`(#,(opswap #'h) . #,(opswap #'t))]
      [_ stx]))
  (syntax-case stx ()
    [(_ condition consequent alternative)
     #`(if condition
           #,(opswap #'consequent)
           #,(opswap #'alternative))]))
> (rev-if #t (+ 5 (- 1 1)) (- 1 10))
3
> (rev-if #f (+ 5 (- 1 1)) (- 1 10))
11
© www.soinside.com 2019 - 2024. All rights reserved.