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))))))