Racket:在子模块中启用涂鸦语言

Racket: enable scribble language in sub module

#lang racket/base
(module x scribble/text
 @(display 123))

似乎#lang 语句在嵌套子模块中无效,上面的扩展模块版本缺少一些东西:

错误:模块:模块语言中没有#%module-begin 绑定

更新:

看起来这样或多或少可行,但有没有更好的方法? scribble 是否对未处理的输出端口执行某些操作?

#lang racket/base
(module x scribble/text/lang
  (#%module-begin
   #reader scribble/reader @list{
     hi
     @(+ 1 456)
  }))

首先,您的代码有多余的 #%module-begin 可以删除。

#lang 做了几件事——一是控制文件的语义 通过确定最初导入的绑定集,那是 module 表格在 #lang 出现之前已经完成的事情。和 子模块,也可以对文件的一部分使用 module。 但是,#lang也可以确定解析文件的reader,并且 这对子模块来说是不可能的,所以你只能用一个 toplevel #lang 为整个文件设置解析器。

(旁注:这是有技术原因的。A #lang reader 读到 文件的其余部分,直到达到 eof 值,因此嵌套 #lang 需要得到一个 eof 值才能结束 文件,或添加一种新的类似eof的值。这意味着它是 一个应该小心完成的改变——这是可能的, 当然,但这种需求出现的频率不够高。希望它会,在 未来。)

但是在你的情况下你不需要一个全新的具体语法,只是 s-expressions 的扩展——以及被选择用于 对常规代码的影响最小。所以在几乎所有情况下都很好 只为整个文件启用@-form 语法,然后使用 @-forms 你想要的地方。因为它只是一种替代方式 阅读 sexprs,您甚至可以将其与 module 一起使用,从而导致此 不需要使用 #reader:

的代码
#lang at-exp racket/base
@module[x scribble/text/lang]{
  hi
  @(+ 1 456)
}
(require 'x)

这里有点奇怪的是使用 scribble/text/lang 和 不只是 scribble/text。通常,#lang foo(module x foo ...) 阅读代码后 foos reader。但在 scribble/text 语言的情况还有另一个区别: 将它用作 #lang 使模块主体的语义成为“输出 每件事”。这个想法是,作为一种 语言 你会想吐出来 主要是文本文件,但作为 您需要在其中编写代码 并自己打印。

由于此代码使用 module,因此使用 scribble/text 意味着您 没有得到 spit-all-out 功能,这就是为什么你需要 明确切换到 scribble/text/lang。但你可以改为 只需使用该语言的 output 自己吐口水,这将 给你这个代码:

#lang at-exp racket/base
(module x racket/base
  (require scribble/text)
  (output @list{
    hi
    @(+ 1 456)}))
(require 'x)

请注意,scribble/text 在这里没有用作语言,因为它 使用时没有提供足够的东西(在 #lang 之外)。 (您已经发现,导致冗余 #%module-begin...)

这个版本稍微冗长一些,但我猜它 在您的情况下更有意义,因为将它用于代码的某些部分意味着 您想将其用作图书馆。

最后,如果您真的不想用 @ 读取整个文件 语法,只有一些部分,那么你找到的 #reader 是 非常好。 (这通过 scribble/text 变得简单 将列表视为串联输出,因此您只需要一个包装器 每个文本块。)