3

好吧,我一定很傻。我正在尝试创建一个宏(一个更大的任务的一部分),它给定一个函数,将它包装在它自己的子模块中,然后require它,这样定义的函数就不会与周围的术语混淆,而是它们的主机的其余部分模块可以正常使用它们。也许这不是一个好主意,但请幽默——我不明白为什么这是不可能的。

我在两个文件中有以下最小代码示例。

tinylang.rkt:

(provide (all-defined-out))

(define-syntax (modularise stx)
  (syntax-case stx ()
[(_ func)
 (with-syntax ([mod (datum->syntax stx 'testmodule)]
               [nm  (datum->syntax stx 'working)]
               )
   #`(begin

       (print (list "Defining module " 'mod))(newline)

       (module mod racket
         (provide nm)
         (define  nm func)
       )

       (require (for-syntax (submod "." mod))) ;; at least kills a syntax error
       (require (for-template (submod "." mod))) ;; doesn't help
    ))]))

tinyimp.rkt:

#lang racket
(require "tinylang.rkt")
(modularise (lambda () (display "this works!")))
; the following line would make everything work!
;(require (submod "." testmodule))
(working)

我对向这个网站发送垃圾邮件感到内疚,我认为这些问题对我来说用文档来解决应该是微不足道的,但我仍然不清楚在什么阶段会发生什么。如果有人知道一个好的资源(书籍、讲座、论文),我会很高兴听到它。我知道 Racket 文档,它非常广泛,但我经常错过那里解释中的关键细节。

4

1 回答 1

3

是的,宏生成的要求和提供很棘手。它们的关键是 require-spec 的词法范围(即(submod "." testmodule))。

文档

在 require ... 中,require-spec 的生成器确定了绑定的范围。

换句话说,require-spec 和所需标识符的使用必须具有相同的范围。

这是一个可以工作的 tinylang.rkt 版本:

#lang racket

(provide (all-defined-out))

(define-syntax (modularise stx)
  (syntax-case stx ()
    [(_ func)
     (with-syntax ([require-spec (datum->syntax stx '(submod "." testmodule))])
       #`(begin
           (module testmodule racket
             (provide working)
             (define working func))
           (require require-spec)))]))
于 2013-09-17T20:48:33.600 回答