Racket 如何使用自定义#%模块开始维护定义功能?

Racket 如何使用自定义#%模块开始维护定义功能?,racket,Racket,我想用我的自定义语言生成的字符串做一些事情,例如显示它们。我创建了一个模块,开始如下操作: (define-syntax (module-begin stx) (syntax-case stx () [(_ EXPR ...) #'(display (apply string-append (filter string? (list EXPR ...))))])) (define-syntax (module-begin stx) (syntax-case stx (

我想用我的自定义语言生成的字符串做一些事情,例如显示它们。我创建了一个模块,开始如下操作:

(define-syntax (module-begin stx)
  (syntax-case stx ()
    [(_ EXPR ...)
     #'(display (apply string-append (filter string? (list EXPR ...))))]))
(define-syntax (module-begin stx)
  (syntax-case stx ()
    [(_ form ...)
     #'(#%plain-module-begin (wrap-module-form form) ...)]))

(define-syntax (wrap-module-form stx)
  (syntax-case stx ()
    [(_ form)
     (let ([e-form (local-expand #'form 'module #f)])
       (syntax-case e-form (begin define-syntaxes define-values #%require #%provide)
         [(define-syntaxes . _)
          e-form]
         [(define-values . _)
          e-form]
         [(#%require . _)
          e-form]
         [(#%provide . _)
          e-form]
         [(begin inner-form ...)
          #'(begin (wrap-module-form inner-form) ...)]
         [expr
          #'(wrap-expression expr)]))]))

(define-syntax (wrap-expression stx)
  (syntax-case stx ()
    [(_ expr) #'(println expr)]))
但是,这阻止我在语言中使用define。我得到错误“define:表达式上下文中不允许”

如何在不失去使用define和其他顶级表达式的能力的情况下获取字符串?我是否需要事先获取所有定义并将其移到开头?

简短答案 使用
开始包装模块
为您完成这项艰巨的工作

(require syntax/wrap-modbeg)
(define-syntax module-begin (make-wrapping-module-begin #'wrap-expression))
(define-syntax (wrap-expression stx)
  (syntax-case stx ()
    [(_ expr) #'(println expr)]))
更改
wrap expression
以对表达式执行任何操作。它不适用于定义、
require
forms等。请注意,一次只能得到一个模块体表达式,而不是一次得到所有表达式

长话短说 您无权注册模块级定义、解释
require
表单等。只有宏扩展器和原语
\%plain module begin
表单才能执行此操作。因此,您的
模块begin
宏必须与它们配合

宏必须使用
local expand
部分展开每个模块级窗体,以便区分以下各项:

  • 模块级定义
  • 要求
    提供
    表格
  • 开始
    序列,需要拼接到模块主体中
  • 表情
当您得到一个定义或
require
provide
表单时,您只需将其扔到真正的
#%plain模块begin
原语。你处理的表达方式;再说一遍,不管你喜欢什么。对于
begin
表单,您的重复出现在子表单上。代码如下所示:

(define-syntax (module-begin stx)
  (syntax-case stx ()
    [(_ EXPR ...)
     #'(display (apply string-append (filter string? (list EXPR ...))))]))
(define-syntax (module-begin stx)
  (syntax-case stx ()
    [(_ form ...)
     #'(#%plain-module-begin (wrap-module-form form) ...)]))

(define-syntax (wrap-module-form stx)
  (syntax-case stx ()
    [(_ form)
     (let ([e-form (local-expand #'form 'module #f)])
       (syntax-case e-form (begin define-syntaxes define-values #%require #%provide)
         [(define-syntaxes . _)
          e-form]
         [(define-values . _)
          e-form]
         [(#%require . _)
          e-form]
         [(#%provide . _)
          e-form]
         [(begin inner-form ...)
          #'(begin (wrap-module-form inner-form) ...)]
         [expr
          #'(wrap-expression expr)]))]))

(define-syntax (wrap-expression stx)
  (syntax-case stx ()
    [(_ expr) #'(println expr)]))

所有新代码基本上都是
使包装模块开始
自动为您所做的。

感谢您提供了详细而全面的答案。我有一个后续问题,尽管这表明了我的无知。如何根据我的问题将表达式包装到列表中?正如您所说,wrap extension宏一次只能处理一个表达式。