Macros 在guile方案中,当从另一个宏调用宏时,如何防止重命名? ;具有创建标识符“self”的定义 (定义BDA的语法) (lambda(stx) (语法大小写stx() [(alambda lambda list.body) (使用语法([name(datum->syntax#'alambda'self)]) #'(letrec([名称(lambda lambda list.body)]) 姓名]])) ; 我想用另一个宏“组合”它 (定义语法规则[apply alambda args argv.body] ((alambda args.body.argv)) ; 但是它不起作用(而alambda本身起作用) (适用于ALMBDA[x][5](如果(=0 x)1(*x(自身(-x 1()))) ; => 未绑定变量:self ; (预计120人)

Macros 在guile方案中,当从另一个宏调用宏时,如何防止重命名? ;具有创建标识符“self”的定义 (定义BDA的语法) (lambda(stx) (语法大小写stx() [(alambda lambda list.body) (使用语法([name(datum->syntax#'alambda'self)]) #'(letrec([名称(lambda lambda list.body)]) 姓名]])) ; 我想用另一个宏“组合”它 (定义语法规则[apply alambda args argv.body] ((alambda args.body.argv)) ; 但是它不起作用(而alambda本身起作用) (适用于ALMBDA[x][5](如果(=0 x)1(*x(自身(-x 1()))) ; => 未绑定变量:self ; (预计120人),macros,scheme,guile,Macros,Scheme,Guile,如何防止apply alambda重命名self 我尝试使用define macro,但由于不同的原因,它也不起作用: (defmacro apply alambda[args argv.body] ((alambda args.body.argv)) ; => lambda:form中的坏lambda(lambda args.body) 在这里,我甚至不知道出了什么问题您的alambda宏不卫生,而且不卫生的宏的组成也不好。基于已用于其他目的的子项创建标识符的不卫生宏的构成尤其糟糕。一种解

如何防止
apply alambda
重命名
self


我尝试使用
define macro
,但由于不同的原因,它也不起作用:

(defmacro apply alambda[args argv.body]
((alambda args.body.argv))
; => lambda:form中的坏lambda(lambda args.body)

在这里,我甚至不知道出了什么问题

您的
alambda
宏不卫生,而且不卫生的宏的组成也不好。基于已用于其他目的的子项创建标识符的不卫生宏的构成尤其糟糕。一种解决方案是创建一个helper宏,该宏将新标识符的“词法上下文”作为单独的参数。然后从中创建派生宏

(define-syntax alambda/lctx
  (lambda (stx)
    (syntax-case stx ()
      [(alambda lctx formals . body)
       (with-syntax ([name (datum->syntax #'lctx 'self)])
         #'(letrec ([name (lambda formals . body)])
             name))])))

(define-syntax alambda
  (lambda (stx)
    (syntax-case stx ()
      [(alambda formals . body)
       #'(alambda/lctx alambda formals . body)])))

(define-syntax apply-alambda
  (lambda (stx)
    (syntax-case stx ()
      [(apply-alambda formals argv . body)
       #'((alambda/lctx apply-alambda formals . body) . argv)])))

(apply-alambda [x] [5] (if (= 0 x) 1 (* x (self (- x 1)))))
alambda
宏中,用于创建
self
活页夹的词汇上下文取自对宏本身的引用。宏在调用
alambda/lctx
时使该参数显式。同样,对于
apply-alambda
——如果要创建另一个扩展为
apply-alambda
的宏,则同样应该创建
apply-alambda/lctx
帮助程序

(在Racket中,词汇上下文不仅附加到标识符,还附加到列表结构(“括号”),不卫生的宏通常使用整个语法对象,如
(datum->syntax stx'self)
。这避免了需要单独的辅助宏。)

注意:使用
define syntax rule
来定义
alambda
apply alambda
不起作用,因为它实际上不会将标识符绑定到运算符位置


您可能会尝试使用
alambda
标识符和对应于
apply alambda
表单使用的词汇上下文来调用
alambda
,如下所示:

(define-syntax bad-apply-alambda
  (lambda (stx)
    (syntax-case stx ()
      [(apply-alambda formals argv . body)
       (with-syntax ([alambda (datum->syntax #'apply-alambda 'alambda)])
         #'((alambda formals . body) . argv))])))
这个版本是错误的。如果在使用
bad apply alambda
的范围内
alambda
未绑定(或绑定到错误的对象),则其行为不正确。例如:

(let ([alambda 5])
  (bad-apply-alambda [x] [5] (if (= 0 x) 1 (* x (self (- x 1))))))