我在 Racket 中编写了一个程序(源代码在 .rkt
文件中,#lang racket
位于顶部)。我还在(主要是)可移植 R7RS 方案中编写了一个库。我可以以干净的方式使用程序中的库吗?
我的目标是让库在 Scheme 实现之间具有广泛的可移植性(至少是符合 R7RS 的实现,理想情况下也包括其他实现)。有第三方R7RS shim for Racket但据我所知,它需要我输入 #lang r7rs
在我的源文件的顶部。我猜这个 #lang
指令会混淆 Racket 以外的 Scheme。
我可以将库的核心放在一个或多个可移植中吗.scm
源文件,然后有一个 .rkt
带有 #lang r7rs
的文件指令告诉 Racket 以某种方式包含可移植文件? Racket 是否理解某种库定义文件,例如 .sld
用于 snow-fort ?
我试图查看整个 Racket 文档,但在任何地方都找不到讨论的内容。我也没有找到一般的 Scheme 可移植性常见问题解答或最佳实践文档。
最佳答案
我设法在实际工作中混合使用 Racket 和 R7RS 代码,并制作了该技术的示例 on GitHub .
这是该存储库中自述文件的副本:
Racket R7RS 垫片
Racket 不附带 R7RS 支持。它在第三方包中r7rs
亚历克西斯·金:https://github.com/lexi-lambda/racket-r7rs
尽管不是 Racket 的官方部分,但它对于
我(我使用了一个中等复杂的库来进行 HTML 解析并编写
一些非常复杂的字符串处理和树在它上面行走,
所以这对实际工作绝对有用)。
您可以通过 raco pkg install r7rs
安装垫片.还要注意的是info.rkt
列表 r7rs
在 Heroku 所需的依赖项中
之类的。
模块
app
-- 一个 Racket 应用 lib
-- app
使用的 R7RS 库sublib
-- lib
使用的 R7RS 库模块由哪些文件组成
所以
app
只需要一个文件,app.rkt
,就像任何普通的 Racket 一样模块。
但是
lib
和 sublib
每个需要3个文件。 lib.scm
是方案代码。
lib.sld
是 Scheme 库定义。和 lib.rkt
是一个它的 Racket 包装。从技术上讲,您可以结合
lib.sld
和lib.scm
合并到一个文件中,但将它们分开会更干净。你也可以将你所有的 Scheme 代码直接复制到
lib.rkt
但是之后你不能将它导入到其他 Schemes 中。
请注意
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
制作,满足pair?
) 默认情况下,而 R7RS 使用可变的 cons 单元格(由Racket 的
mcons
,满足mpair?
)。也就是说,当您拨打 cons
时在 Scheme 方面,它实际上做了一些看起来像 Racket 的东西
好像你打过电话
mcons
在 Racket 一侧。可变的缺点意味着您可以使用 Scheme 的
set-car!
和 set-cdr!
将其更改到位,而一个不可变的 cons 的 car 和 cdr 不能改变
初始
cons
.默认情况下,Racket 显示由可变 conses 组成的列表,使用
{curly braces}
而不是 (ordinary parentheses)
.这会咬人当您通过 R7RS-Racket 边界传递列表时。你可以打印
通过更改
print-mpair-curly-braces
使用普通括号参数,但对于许多事情,转换列表可能更容易
(和树)从可变到不可变。
不知道 Racket R7RS shim 是否可以让你不可变
方案方面的缺点。有一个选项会很好
方案
cons
做出不可变的结论(在这种情况下 set-car!
和set-cdr!
会导致错误,这对于仅使用的代码很好不可变的数据结构)。
在哪里可以找到 R7RS 库
许多 R7RS 库由 Alex Shinn 在
http://snow-fort.org/
底线
所有这一切的结果是,您可以将 R7RS 和 Racket 与
很少工作,您的代码库保持非常干净(至少对于简单的
案例)。
关于scheme - 在 Racket 程序中使用 Scheme 库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55242394/