Racket/Scheme - 句法-Case

4

我目前正在进行一项关于racket宏的任务。在其中一个问题中,我们被要求定义一个名为my-set!的宏,其作用如下:

(define x 3)
(define y 5)
(define z 7)
(my-set! (x (+ x y)))
(my-set! (x (+ x y)) (z 6))
x
13
y
5
z
6

我在syntax-case上发现了这份有趣的文档http://www.cs.indiana.edu/~dyb/pubs/tr356.pdf
目前我的宏已经可以工作,但是我正在尝试像文档第10页上那样添加一个"fender"来防止变量不是标识符或其他任何错误。
这是我的代码:
(define-syntax my-set!
  (letrec ((all-ids?
            (λ (ls)
              (or (null? ls)
                  (and (identifier? (car ls))
                       (all-ids? (cdr ls)))))))
    (lambda (x)
      (syntax-case x ()
        ((_ (var val) (var2 val2) (var3 val3) ...)
         (all-ids? (syntax (var var2 var3 ...)))
         (syntax (begin (set! var val) (my-set! (var2 val2) (var3 val3) ...))))
        ((_ (var val))
         (syntax (set! var val)))))))

如果我测试这段没有挡泥板的代码,它完美运行。但当我运行这段代码时:
(define a 1)
(define b 1)
(define c 1)

(my-set! (a 3) (b 4) (c 5))

我得到了这个:

错误:违反合同的期望:pair?
给定:syntax:C:\Users\mgiroux\Desktop\define-myset.rkt:40:26 (a b c)

看起来像是all-ids?不能对(a b c)的(car)进行操作,因为它不是一个列表?我尝试将其作为列表传递,但也没有起作用,我似乎复制了我链接的pdf中的方式。我在这里缺少什么?
1个回答

3

#'(var var2 var3 ...)实际上不是一个列表,而是一个包装列表的语法对象。您应该使用syntax->list将项目提取到列表中,因此您的守卫应该如下所示:

(all-ids? (syntax->list #'(var var2 var3 ...)))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接