Macros 设置全局方案宏?
我正在尝试为Macros 设置全局方案宏?,macros,lisp,scheme,racket,Macros,Lisp,Scheme,Racket,我正在尝试为define编写一个包装器,用于存储传递给它的值。我一直在以很小的步伐接近它(对于Lisp一般来说是新的,对于Scheme来说甚至是更新的),但是遇到了一堵墙 在《球拍》中,我从以下几点开始: > (require (lib "defmacro.ss")) > (define-macro (mydefine thing definition) `(define ,thing ,definition)) > (mydefine a 9) > a 9
define
编写一个包装器,用于存储传递给它的值。我一直在以很小的步伐接近它(对于Lisp一般来说是新的,对于Scheme来说甚至是更新的),但是遇到了一堵墙
在《球拍》中,我从以下几点开始:
> (require (lib "defmacro.ss"))
> (define-macro (mydefine thing definition)
`(define ,thing ,definition))
> (mydefine a 9)
> a
9
好的,这样行。在返回s-EXPR之前,在宏中执行某些操作的时间:
> (define-macro (mydefine thing definition)
(display "This works")
`(define ,thing ,definition))
> (mydefine a "bob")
This works
> a
"bob"
很好。但我无法让它设置一个全局变量,而不是显示某些内容:
> (define *myglobal* null)
> (define-macro (mydefine thing definition)
(set! *myglobal* "This does not")
`(define ,thing ,definition))
> (mydefine a ":-(")
set!: cannot set identifier before its definition: *myglobal*
任何关于如何实现这一目标的建议都将不胜感激
我怀疑我试图逆流而上,要么在Scheme中通过摆弄宏中的全局变量,要么使用define macro而不是学习特定于Scheme的宏创建语法。语句(set!*myglobal*“This nots”)
在transformer环境中执行,不是正常的环境。因此它无法找到*myglobal
。我们需要在定义了*myglobal*
的环境中执行这两个表达式
这里有一个解决方案:
(define *defined-values* null)
(define-macro (mydefine thing definition)
`(begin
(set! *defined-values* (cons ,definition *defined-values*))
(define ,thing ,`(car *defined-values*))))
> (mydefine a 10)
> (mydefine b (+ 20 30))
> a
10
> b
50
> *defined-values*
(50 10)
> (define i 10)
> (mydefine a (begin (set! i (add1 i)) i)) ;; makes sure that `definition`
;; is not evaluated twice.
> a
11
如果方案实现没有提供define宏
,但有define语法
,mydefine
可以定义为:
(define-syntax mydefine
(syntax-rules ()
((_ thing definition)
(begin
(set! *defined-values* (cons definition *defined-values*))
(define thing (car *defined-values*))))))
您正在运行Racket的阶段分离——这意味着每个阶段(运行时和编译时)在不同的世界中运行。正如Vijay所指出的,解决这一问题的一种方法是在运行时执行您想要的操作,但从长远来看,这可能不是您所需要的。问题是,尝试这些东西通常意味着您需要在编译时级别存储一些语法信息。例如,假设要存储所有已定义名称的名称,以便在第二个宏中使用,该宏将全部打印出来。您可以按如下方式执行此操作(我在这里使用sane宏,
define macro
是一种不应用于实际工作的遗留攻击,您可以在中查找这些内容,然后在中查找):
请注意,定义的名称
是在语法级别定义的,这意味着正常运行时代码不能引用它。事实上,您可以在运行时级别将其绑定到不同的值,因为这两个绑定是不同的。至此,您就可以编写使用它的宏了--即使在运行时无法访问定义的名称
,但它在语法级别上是一个普通绑定,因此:
(define-syntax (show-definitions stx)
(syntax-case stx ()
[(_) (with-syntax ([(name ...) (reverse defined-names)])
#'(begin (printf "The global values are:\n")
(for ([sym (in-list '(name ...))]
[val (in-list (list name ...))])
(printf " ~s = ~s\n" sym val))))]))
(define-syntax (show-definitions stx)
(syntax-case stx ()
[(_) (with-syntax ([(name ...) (reverse defined-names)])
#'(begin (printf "The global values are:\n")
(for ([sym (in-list '(name ...))]
[val (in-list (list name ...))])
(printf " ~s = ~s\n" sym val))))]))