#%module-begin
首先,您的代码有一个可以删除的冗余。
#lang
做了几件事——一个是通过确定最初导入的绑定集来控制文件的语义,这是module
表单在出现之前所做的事情#lang
。使用子模块,也可以module
用于文件的某些部分。但是,#lang
也可以确定解析文件的阅读器,而子模块无法做到这一点,因此您只能使用一个顶层#lang
来设置整个文件的解析器。
(旁注:这是有技术原因的。#lang
阅读器读取文件的其余部分直到它达到一个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
. 通常,与用s reader阅读代码后#lang foo
完全一样
。但就语言而言,还有另一个区别:将其用作 a会使模块主体的语义成为“输出每一件事”。这个想法是,作为一种语言,您将希望输出主要是文本文件,但作为一种库,您将希望在其中编写代码并自己进行打印输出。(module x foo ...)
foo
scribble/text
#lang
由于此代码使用module
, usingscribble/text
意味着您没有获得全部吐出功能,这就是您需要显式切换到scribble/text/lang
. 但是您可以改用该语言的 s 自己吐口水output
,这将为您提供以下代码:
#lang at-exp racket/base
(module x racket/base
(require scribble/text)
(output @list{
hi
@(+ 1 456)}))
(require 'x)
请注意,scribble/text
这里不用作一种语言,因为它在使用时(在 a 之外)没有提供足够的东西来成为一种语言#lang
。(你已经发现,导致冗余#%module-begin
......)
这个版本稍微有点冗长,但我猜它在你的情况下更有意义,因为将它用于代码的某些部分意味着你想将它用作库。
最后,如果您真的不想阅读整个文件的@
语法,只阅读一些部分,那么#reader
您找到的就很好。(这很简单,scribble/text
因为将列表视为连接输出,因此每个文本块只需要一个包装器。)