Macros 方案宏展开显示变量未绑定
我正在编写一个简单的lisp解释器,在阅读lisp的小片段时,我被这个错误困扰了2个多小时。我正在定义一个本地Macros 方案宏展开显示变量未绑定,macros,scheme,Macros,Scheme,我正在编写一个简单的lisp解释器,在阅读lisp的小片段时,我被这个错误困扰了2个多小时。我正在定义一个本地genv变量,但仍然出现此错误。一定有一些宏扩展的东西我不明白,我已经用引号检查了扩展,看起来还可以。拜托,如果有人能给我点启示那就太好了。(该代码使用r5rs语言和guile方案) 问题代码: ;; ------------PROBLEM IN THESE MACROS------------------ (define-syntax _def-initial (syntax-r
genv
变量,但仍然出现此错误。一定有一些宏扩展的东西我不明白,我已经用引号检查了扩展,看起来还可以。拜托,如果有人能给我点启示那就太好了。(该代码使用r5rs语言和guile方案)
问题代码:
;; ------------PROBLEM IN THESE MACROS------------------
(define-syntax _def-initial
(syntax-rules ()
((_def-initial name)
(update 'name 'void genv))
((_def-initial name value)
(update 'name value genv))))
(define-syntax _def-primitive
(syntax-rules ()
((_def-primitive name value arity)
(_def-initial name (lambda (args)
(if (equal? arity (length args))
(apply value args)
(error "Incorrect arity" (list 'name value))))))))
(define-syntax _fill-global-env
(syntax-rules ()
((_fill-global-env)
(begin
(println "Filling the environment")
(_def-primitive + (lambda (x y) (+ x y)) 2)
(_def-primitive - (lambda (x y) (- x y)) 2)
(_def-primitive * (lambda (x y) (* x y)) 2)
(_def-primitive / (lambda (x y) (/ x y)) 2))
)))
;; Racket and Guile SAY genv IS UNBOUND
(define get-global-environment
;; name must be `genv' coz of the above macros
(let ( (genv #f) )
(lambda ()
(if (equal? genv #f) ;; If uninitialized
(begin (set! genv (make-new-environment '()))
(println "Before filling: "genv)
(_fill-global-env)
(println "After filling: " genv)
genv)
genv))))
;; ------------------- END OF PROBLEMATIC CODE(IT SEEMS) ---------------
继续:
;; - Start the interpreter
(define (main args)
;; Define the global environment
(define genv (get-global-environment))
(println "Global environment: " genv)
(let loop ((expr (read (current-input-port))))
(if (eof-object? expr)
(println "Done")
(begin (println (evaluate expr genv))
(loop (read (current-input-port)))))))
(main "")
以下是我从Racket收到的错误(在有问题代码的get global environment
主体中,而不是main
主体中):
方案宏是。您在get global environment
中定义的genv
与您在\u def-initial
中定义的genv
不同(它使用定义\u def-initial
时存在的genv
,在这种情况下,它将是顶级的,正如您所指出的,它并不存在)
为了使宏正常工作,您必须调整
\u fill-global-env
、\u def-primitive
和\u def-initial
以使用\u def-initial
参数,以便\u def-initial
使用genv
而不是顶级参数。这似乎是我从(\u fill-global-env)得到的扩展Chris已经回答了,但是我想在println
中提到((uexpr)(begin(display expr)(newline))
是多余的,因为模式(expr expr*…)
匹配1到n个参数。(expr*…
可以匹配零元素)。@Sylvester确实如此,因为它是在1+的情况下出现的,所以它甚至永远不会开火。@Sylvester哦,我明白了。啊,我明白了。非常感谢,关于scheme的宏,我还有很多东西要学习。(这本书在顶层有全局env变量,我试图将其保留在主程序中,只是因为:。|)我接受你的答案。
;; - Start the interpreter
(define (main args)
;; Define the global environment
(define genv (get-global-environment))
(println "Global environment: " genv)
(let loop ((expr (read (current-input-port))))
(if (eof-object? expr)
(println "Done")
(begin (println (evaluate expr genv))
(loop (read (current-input-port)))))))
(main "")
. . genv: undefined;
cannot reference undefined identifier