2017-05-07 70 views
1

在Gambit方案中,如果我编译文件,我似乎无法在另一个宏的定义中调用宏。这是一个人为的例子:宏调用宏在Gambit方案中给出了“未定义变量”

;;;; example.scm 

(define-macro (w/gensyms gs body) 
    `(let ,(map (lambda (g) `(,g (gensym ',g))) 
       gs) 
    ,body)) 

(define-macro (compose-macro f g) 
    (w/gensyms (x) 
    `(lambda (,x) (,f (,g ,x))))) 

(define my-cadr 
    (lambda (x) 
    ((compose-macro car cdr) x))) 

;; $ gsc example.scm 
;; *** ERROR IN #<procedure #2> -- Unbound variable: w/gensyms 

但是,如果我加载与(include ...)特殊形式的文件中解释,它的工作原理

$ gsi 
> (include "example.scm") 
> (pp my-cadr) 
(lambda (x) ((lambda (#:x0) (car (cdr #:x0))) x)) 

有谁知道这是怎么回事?我能否说服Gambit让我在编译的文件中定义另一个宏时使用w/gensyms?

+0

我知道我不应该使用定义宏 – scpayson

回答

0

这很可能与阶段有关。

试试这个:

w/gensyms在文件a.scm,并在进口a.scm文件b.scm把compose-macro

+0

进口怎么样?根据手册手册,我需要使用include来拼接宏定义。 – scpayson

+0

如果我理解正确,Gambit使用一个名为Black Hole的模块系统:http://dynamo.iro.umontreal.ca/wiki/images/3/30/Black_Hole_Core.pdf – soegaard

0

这是一个阶段性问题。您希望w/gensyms的定义在后续宏的主体中可用。这可以通过对语法宏迫使宏定义的评价在语法扩张时间来实现:

(define-macro (for-syntax . body) 
    (eval `(begin ,@body)) 
    `(begin)) 

(for-syntax 
(define-macro (w/gensyms gs body) 
    `(let ,(map (lambda (g) `(,g (gensym ',g))) 
       gs) 
     ,body))) 

如果你想宏可以从其他宏定义内和非宏定义中都代码,你可以用这个来代替:

(define-macro (for-syntax . body) 
    (eval `(begin ,@body)) 
    `(begin ,@body)) 

对于这个具体的例子,因为你正在使用的一个地方的宏,你可以这样做:

(define-macro (compose-macro f g) 

    (define-macro (w/gensyms gs body) 
    `(let ,(map (lambda (g) `(,g (gensym ',g))) 
       gs) 
     ,body)) 

    (w/gensyms (x) 
    `(lambda (,x) (,f (,g ,x))))) 

一个相关的办法来解决问题,逐步就是把定义的W /文件“macros.scm”在与gensyms等宏做:

(define-macro (compose-macro f g) 

    (include "macros.scm") 

    (w/gensyms (x) 
    `(lambda (,x) (,f (,g ,x)))))