Racket:在子模块中启用scribble语言

时间:2015-06-28 23:12:42

标签: racket scribble

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

1 个答案:

答案 0 :(得分:4)

首先,您的代码有一个可以删除的冗余#%module-begin

#lang做了几件事 - 一个是控制文件的语义 通过确定最初导入的绑定集,那就是 在module出现之前#lang表单已完成的内容。同 子模块,也可以将module用于文件的各个部分。 但是,#lang也可以确定解析文件的读者,以及 这是不可能的子模块,所以你只有一个 toplevel #lang为整个文件设置解析器。

(旁注:有一个技术原因。#lang读者读到 文件的其余部分,直到达到eof值,因此嵌套 #lang需要在结束之前获得eof值 该文件,或添加一种新的类似eof的值。这意味着它 应该谨慎进行的改变 - 这是可能的 当然,但需求并没有经常出现。希望它会,在 未来。)

但是在你的情况下,你不需要一个全新的具体语法 s表达式的扩展 - 以及被选择的扩展名 对常规代码影响最小。所以在几乎所有情况下都很好 只为整个文件启用@ -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 ...)读者阅读代码后foo。但在 scribble/text语言的情况还有另一个区别: 使用它作为#lang使模块体的语义成为“输出 每一件事“。这个想法是,作为一种语言,你会想要吐出来 主要是文本文件,但作为,您需要在其中编写代码 并自己做打印输出。

由于此代码使用module,因此使用scribble/text意味着您 没有得到吐出全部功能,这就是你需要的原因 明确切换到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这简单易懂 将列表视为连接输出,因此您只需要一个包装器 每一块文字。)