2
#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)
  }))
4

1 回答 1

4

#%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 ...)fooscribble/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因为将列表视为连接输出,因此每个文本块只需要一个包装器。)

于 2015-06-29T08:40:10.240 回答