Macros 方案宏展开显示变量未绑定

Macros 方案宏展开显示变量未绑定,macros,scheme,Macros,Scheme,我正在编写一个简单的lisp解释器,在阅读lisp的小片段时,我被这个错误困扰了2个多小时。我正在定义一个本地genv变量,但仍然出现此错误。一定有一些宏扩展的东西我不明白,我已经用引号检查了扩展,看起来还可以。拜托,如果有人能给我点启示那就太好了。(该代码使用r5rs语言和guile方案) 问题代码: ;; ------------PROBLEM IN THESE MACROS------------------ (define-syntax _def-initial (syntax-r

我正在编写一个简单的lisp解释器,在阅读lisp的小片段时,我被这个错误困扰了2个多小时。我正在定义一个本地
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