【问题标题】:Require identifiers not provided by a module in Racket需要 Racket 中的模块未提供的标识符
【发布时间】:2016-03-11 09:39:43
【问题描述】:

假设我有一些文件a.rkt:

#lang racket
(define a 12)

我现在想写一些测试用例,使用需要a.rkt的文件b.rkt

#lang racket
(require "a.rkt")
a

有什么方法可以让b.rkt 识别a.rkt 中定义的标识符,而不必从第一个文件中识别provide? (理想情况下根本不必更改第一个文件。)

我没有立即在 the documentation for require/provide 中看到任何内容。

【问题讨论】:

  • 自我回答问题的好主意,但您可能想在问题中添加更多动力。即,澄清这是为了测试,而不是您通常想要做的事情。
  • 这个主意不错,我会改的。

标签: scheme racket


【解决方案1】:

正如 Leif 所提到的,RackUnit 的 require/expose允许在其他模块中使用未提供的标识符,但 its own documentation 并没有承诺非常有力的保证:

请注意,require/expose 可能有点脆弱,尤其是在与编译代码混合时。使用风险自负!

另一种方法是使用submodules,它可以有效地提供一种经认可的方式来导出私有 API 以用于测试或其他方式。

例如,考虑一个模块,它实现了一个函数来测试一个字符串是否包含一个单词:

#lang racket

(provide word?)

(define (word? str)
  (not (ormap space? (string->list str))))

(define (space? c)
  (eq? c #\space))

(这可能不是最现实的例子,但请耐心等待。)

测试space? 函数以确保其正常工作可能很有用,但它可能不应该成为公共 API 的一部分。要创建“逃生舱”,可以定义一个导出此绑定的子模块:

(module+ for-testing
  (provide space?))

for-testing 这个名字是任意的——它可以是任何东西。无论哪种方式,现在都可以要求另一个模块中的子模块访问私有绑定:

#lang racket

(require rackunit
         (submod "a.rkt" for-testing))

(check-true (space? #\space))
(check-false (space? #\a))

这是一种从模块中公开标识符而不向所有消费者公开的更安全的方法。

【讨论】:

  • 有时,更改原始来源以添加额外的provides 是不可行的,例如,不听从指示的学生。 Dan Feltey 的测试框架以这种方式使用require/expose(和朋友):github.com/dfeltey/pdptest。 (与您的回答不矛盾,只是描述另一个用例上下文。)
【解决方案2】:

您可以使用b.rkt 中的require/expose 来访问a.rkt 中的绑定。 b.rkt 看起来像这样:

#lang racket
(require rackunit)
(require/expose "a.rkt" (a))
a

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多