【问题标题】:Using Scheme libraries in a Racket program在 Racket 程序中使用 Scheme 库
【发布时间】:2019-08-10 01:30:17
【问题描述】:

我在 Racket 中编写了一个程序(源代码在 .rkt 文件中,顶部有 #lang racket)。我还在(主要是)便携式 R7RS 方案中编写了一个库。我可以以干净的方式使用程序中的库吗?

我的目标是让库在 Scheme 实现之间广泛移植(至少是符合 R7RS 的,理想情况下也是其他的)。有一个第三方R7RS shim for Racket,但据我所知,它要求我在源文件的顶部键入#lang r7rs。我认为这个 #lang 指令会混淆 Racket 以外的方案。

我可以将我的库的核心放在一个或多个可移植的.scm 源文件中,然后有一个带有#lang r7rs 指令的.rkt 文件,告诉Racket 以某种方式包含可移植文件吗? Racket 是否理解某种库定义文件,例如 snow-fort 上使用的 .sld

我试图查看整个 Racket 文档,但在任何地方都找不到讨论的内容。我也没有找到通用的 Scheme 可移植性常见问题解答或最佳实践文档。

【问题讨论】:

  • R6RS 使用#!r6rs,在球拍中被理解为. #lang r6rs。我认为#!r7rs 应该可以工作,但我找不到关于它的文档。
  • 不幸的是,R7RS-small 规范没有提到#!r7rs。奇怪的是它在旧标准中,但不在新标准中。
  • 仅供参考:Racket slack 频道(包括实施#lang r7rs 的频道)看到并讨论了您的问题,但似乎没有好的答案。如果您注册一个帐户,您将可以在这里看到讨论:racket.slack.com/archives/C06V96CKX/p1553004312909000

标签: scheme racket


【解决方案1】:

我设法将 Racket 和 R7RS 代码混合用于实际工作,并以on GitHub 技术为例。

这是该仓库的自述文件的副本:


球拍 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,就像任何普通的球拍一样 模块。

但是libsublib 分别需要 3 个文件。 lib.scm 是方案 代码。 lib.sld 是 Scheme 库定义。而lib.rkt 是一个 球拍包装。从技术上讲,您可以结合 lib.sldlib.scm 放在一个文件中,但将它们分开会更干净。你 也可以将您的所有 Scheme 代码直接复制到 lib.rkt 但随后 您不能将其导入其他方案。

请注意,lib.scm 顶部没有 (import ...) 表单。 导入位于lib.sld 中的define-library 表单内。这 define-library 表单使用 (include ...) 包含实际代码 在lib.scm

lib.rkt 的工作只是对 Racket 说#lang r7rs 然后 包括方案的东西。首先需要(import (scheme base)) 这样我们就可以使用includeexport。包含的.sld 文件 从库的 Scheme 标准中导入所有其他内容 需要。

请注意 lib 依赖于 sublibsublib 不是由 lib.sld 中的 define-library 表单。相反,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 单元格(由 球拍的mcons,满足mpair?)。也就是说,当你打电话给cons 在 Scheme 方面,它实际上做了一些看起来像 Racket 就好像您在球拍端调用了mcons。可变的缺点意味着 你可以使用 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 制作不可变的conses(在这种情况下set-car!set-cdr! 会导致错误,这对于仅使用的代码很好 不可变的数据结构)。

在哪里可以找到 R7RS 库

Alex Shinn 收集了很多 R7RS 库 http://snow-fort.org/

底线

这一切的结果是您可以将 R7RS 和 Racket 与 很少的工作,你的代码库保持很干净(至少对于简单的 例)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-24
    • 2011-05-30
    • 2018-11-10
    • 2014-03-08
    • 1970-01-01
    • 1970-01-01
    • 2011-03-21
    相关资源
    最近更新 更多