在 Racket 中重新绑定名称 `module`

Rebinding the name `module` in Racket

我想让 Racket 评估 .kicad_mod 文件的语法,这些文件是以下形式的 s 表达式数据:

(module LED-10MM (layer F.Cu) (tedit 55BDE3C5)
  (descr "LED 10mm")
  ...)

full file here

我希望能够混合使用 Racket 和 "kicad_mod" 语法,所以我试图重新定义 module 函数。作为开始,我尝试了:

;kicad_mod.rkt

#lang racket
(provide
 (except-out (all-from-out racket) #%module-begin module)
 (rename-out [module-begin #%module-begin]))

(define kicad_module "you got me")

(define-syntax-rule (module-begin expr ...)
  (#%module-begin
   (provide (rename-out [kicad_module module]))))

以及在加载端最终起作用的方法(虽然不是在 drracket 中,而是直接使用球拍解释器):

;main.rkt

#lang racket
(module kicad_mod "kicad_mod.rkt")
(require 'kicad_mod)
(println module)
; => "you got me"

但是,如果我尝试任何其他方式,它都会失败:

1.

;main.rkt

#lang racket
(require "kicad_mod.rkt")` 

导致错误:

 main.rkt:3:9: module: bad syntax
      in: module
      context...:
       standard-module-name-resolver

2.

;main.rkt

#lang s-exp "kicad_mod.rkt"
(println module)

导致标准输出无输出

这不是答案,但我不能在评论中写代码。

这看起来很奇怪 - 表达式不应该在输出中吗?

(define-syntax-rule (module-begin expr ...)
  (#%module-begin
   (provide (rename-out [kicad_module module]))))

也许

(define-syntax-rule (module-begin expr ...)
  (#%module-begin
   (provide (rename-out [kicad_module module]))
   expr ...))

(define-syntax-rule (module-begin expr ...)
  (#%module-begin
   (provide (rename-out [kicad_module module]))
   'expr ...))

?

尽管这不是完整的答案。

我所做的事情没有多大意义,因为我不理解 #%module-begin 重新定义以及在什么上下文中调用代码。

如果您修改 kicad_mod.rkt 以包含像 soegaard 建议的引用表达式:

(define-syntax-rule (module-begin expr ...)
  (#%module-begin
   (provide (rename-out [kicad_module module]))
   'expr ...))

并拥有:

;main.rkt
#lang s-exp "kicad_mod.rkt"
(println module)

你实际上在 stdout 上得到了 '(println module) 的输出。所以 (provide (rename-out... 是在模块的上下文中使用我们的新语言调用的,就在表达式之前执行(如果你像 soegaard 最初的建议那样从 expr 中删除引号)。

我真正想要的是在那之前重新定义module,同时我正在重新定义#%module-begin:

;kicad_mod.rkt

#lang racket
(provide
 (except-out (all-from-out racket) #%module-begin module)
 (rename-out [module-begin #%module-begin])
 (rename-out [kicad_module module]))

(define kicad_module "you got me")

(define-syntax-rule (module-begin expr ...)
  (#%module-begin
   expr ...))

这将与上面使用 #lang s-expmain.rkt 一起正常工作。您仍然需要 #%module-begin 绑定,尽管如果您想使用 #lang s-exp,此时它什么都不做。无论如何它以后都会派上用场的,我相信。