在我上的一堂课中,我们使用Scheme的旧R5RS标准来解决SICP分配。我喜欢先进行测试开发,因此我认为单元测试框架会很不错,因此我选择SchemeUnit编写小型测试。
到目前为止,这已经很好用了,只测试了输出中的原语(字符串,数字等),但是在尝试测试列表时遇到了障碍。它可能与用于运行测试的Scheme方言的差异有关:
foo.scm: (define a-list (list 2))
foo-tests.scm: (check-equal? a-list (list 2))
运行测试的结果:
Unnamed test
FAILURE
name: check-equal?
location: tester.scm:22:3
actual: {2}
expected: (2)
为了使测试套件运行,我必须在foo-tests.scm的顶部添加
"#lang scheme/base
,并在schemeunit软件包中添加require
。在foo.scm中,我需要在顶部放置#lang r5rs
和(#%provide (all-defined))
。我想列表在R5RS和“方案/基础”中以某种方式实现了不同。有什么办法可以让他们一起工作?为何失败({} vs())?
最佳答案
是的,您已经注意到,列表在#lang r5rs
和#lang scheme/base
中的实现方式有所不同。如果可以在r5rs中的foo-tests.scm
中编写测试,则将有助于消除可能的混淆。
您应该可以通过将其放在foo-tests.scm
文件的顶部来执行此操作。
#lang r5rs
(#%require schemeunit)
(#%require "foo.scm")
;; Now you can add your tests here:
(check-equal? a-list (list 1 2 3))
如果测试套件是用相同的语言编写的,则结构---尤其是列表的表示形式–应该匹配。以上测试有望通过。
要详细说明
r5rs
列表与#lang scheme
(和#lang racket
)中的列表之间的区别:Racket使用不可变的cons对表示列表。不可变的缺点对不支持r5rs的set-car!
和set-cdr!
函数,因此使用内置的不可变对对#lang r5rs
语言的标准并不忠实。为了支持r5rs标准,Racket包含了一个单独的mutable pairs数据类型,并在r5rs中一致地使用它。但这意味着Racket中的标准对和可变对之间的比较并不相同。