像快速失败测试一样运行SICP Scheme文件



经过几年的编程,似乎是时候攻击SICP了。但是,我宁愿使用不同的编辑器和简单的makefile来运行所有练习,而不是在Emacs中编辑和运行所有内容。这似乎并不完全符合标准,因为我找不到任何关于运行文件的基本参考,直到出现"失败"。那么,我如何在shell上运行Scheme,使它加载文件,按顺序计算每个表达式,并在遇到计算结果为#f的语句时以非零退出代码终止,或者如果整个文件成功计算,则以零退出代码终止?到目前为止最接近解决方案的东西:

$ cat ch1.scm
...
(= 1 2)
$ scheme --load ch1.scm
...
Loading "ch1.scm"... done
1 ]=>

编辑:换句话说,是否有某种方法可以在ch1加载期间停止求值。如果其中任何表达式求值为#f ?

如果您不想使用成熟的单元测试库(可以理解),那么您可以选择自己编写。您可以使用read从文件中读取s表达式,使用eval对它们进行评估并测试它们是否为假,然后返回报告,如果发现假则退出。像这样的代码应该可以工作:

(define (read-and-test filename env)
  (call-with-input-file
      filename
    (lambda (in)
      (let loop ((input (read in)))
        (if (eof-object? input)
            (display "done!")
            (begin
              (if (eval input env)
                  (begin
                    (display input)
                    (display " ok")
                    (newline)
                    (loop (read in)))
                  (begin
                    (display "failed on ")
                    (display input)
                    (newline)
                    (exit)))))))))

如果你把上面的代码放在一个名为unit.scm的文件中,而你想测试的文件名为test.scm,你可以在Unix命令行中用MIT Scheme调用它,像这样:

mit-scheme --load `pwd`/unit.scm --eval '(read-and-test "/Users/aki/code/scratch/test.scm" (the-environment))'

(注意上面有一些MIT Scheme特定的东西,与eval和环境有关)

我可以想到两种方法。蛮力的方法是编写一个expect脚本,将scheme作为一个低级进程运行,每次输入一行并检查返回的输出——基本上,就像一个机器人。更优雅的方法是将模式解释器中的顶级REPL替换为一个在表达式求值为#f时退出的REPL。

相关内容

最新更新