我用Racket编写了一个程序(源代码在顶部的.rkt文件中#lang racket)。我还用(主要)便携式R7RS Scheme写了一个库。我可以以干净的方式在程序中使用该库吗?
我的目标是使该库在Scheme实现之间具有广泛的可移植性(至少是与R7RS兼容的实现,理想情况下还应是其他实现)。Racket有一个第三方R7RS填充程序,但据我所知,它要求我#lang r7rs在源文件的顶部键入内容。我猜想该#lang指令会使Racket之外的Scheme感到困惑。
我可以将库的核心放在一个或多个可移植的.scm源文件中,然后.rkt使用#lang r7rs指令告诉Racket以某种方式包括可移植文件的文件来包含一个文件吗?Racket是否了解某种库定义文件,例如.sld用在雪地上的库定义文件?
我试图浏览整个Racket文档,但在任何地方都找不到。我也没有找到通用的计划可移植性常见问题解答或最佳做法文档。
我设法将 Racket 和 R7RS 代码混合用于实际工作,并在 GitHub 上制作了该技术的示例。
这是该存储库中的自述文件副本:
Racket 不附带 R7RS 支持。r7rs它位于Alexis King 的第三方包中
:https: //github.com/lexi-lambda/racket-r7rs
尽管不是 Racket 的官方部分,但它对我来说工作得很好(我使用了一个中等复杂的库来完成HTML 解析并在其上编写了一些复杂的字符串处理和树遍历,因此这对于实际工作绝对有用)。
您可以通过安装垫片raco pkg install r7rs。另请注意,
依赖项中info.rkt列出了r7rsHeroku 等所需的依赖项。
app-- 球拍应用程序lib-- 使用的 R7RS 库appsublib-- 使用的 R7RS 库lib因此app只需要一个文件,app.rkt就像任何普通的 Racket 模块一样。
但每个lib需要sublib3 个文件。lib.scm是方案代码。lib.sld是Scheme库定义。并且lib.rkt是它的球拍包装。从技术上讲,您可以将lib.sld和
合并lib.scm到一个文件中,但将它们分开会更干净。您也可以将所有方案代码直接复制到其中lib.rkt,但无法将其导入其他方案。
请注意,顶部lib.scm没有表格。(import ...)导入内容define-library位于lib.sld. 该
define-library表单用于(include ...)将实际代码包含在lib.scm.
的工作lib.rkt只是#lang r7rs向 Racket 说,然后包括计划的东西。首先需要这样(import (scheme base))
我们才能使用include和export。包含的.sld文件导入库所需的Scheme 标准中的所有其他内容。
请注意,lib依赖于sublib但sublib不由define-library中的表单导入lib.sld。相反,lib.rkt必须加载 lib及其所有依赖项:除了(include "sublib.sld")
明显的(include "lib.sld").
因此lib.sld,仅导入来自Scheme 标准的内容,而
lib.rkt导入我们所有的自定义库。我不得不求助于这个 hack,因为我无法让 Racket 模块查找器来查找sublib
我是否将其放入(define-library ...)导入中。我根本没有努力,所以很可能有办法让它发挥作用。
默认情况下,Racket 使用不可变的 cons 单元(由 Racket 制作cons,满足
),而 R7RS 使用可变 cons 单元(由 Racket 制作,满足)。也就是说,当你
在Scheme端调用时,它实际上会做出一些在Racket看来就像你在Racket端调用一样的东西。可变 cons 意味着您可以使用Scheme并就地更改它,而不可变 cons 的 car 和 cdr 在初始.pair?mconsmpair?consmconsset-car!set-cdr!cons
{curly braces}默认情况下,Racket 使用而不是显示由可变 cons 组成的列表
(ordinary parentheses)。当你通过 R7RS——球拍边界的列表时,这会咬住你。您可以通过更改参数来使用普通括号进行打印print-mpair-curly-braces
,但对于许多事情来说,将列表(和树)从可变转换为不可变可能更容易。
我不知道 Racket R7RS shim 是否允许您在方案方面做出不可变的conses。cons如果方案有一个选项可以制作不可变的conses,那就太好了(在这种情况下set-car!,
set-cdr!会导致错误,这对于仅使用不可变数据结构的代码来说很好)。
Alex Shinn 在http://snow-fort.org/收集了许多 R7RS 库
所有这一切的结果是,您可以通过一些工作混合 R7RS 和 Racket,并且您的代码库保持相当干净(至少对于简单的情况)。