我正在尝试在方案中编写自己的单元测试库。到目前为止,我在定义窗口中有以下代码:
#lang scheme
(define all-tests '())
(define-syntax make-tests
(syntax-rules (->)
[(_ test-name function (args ... -> result) ...)
(begin
(define test-name
(list function (list (list args ...) ...) (list result ...)))
(set! all-tests (cons test-name all-tests)))]))
使用Dr. Racket,当我将以下代码提交到REPL中时:
> (make-tests tests + (1 2 -> 3))
set!: assignment disallowed;
cannot modify a constant
constant: all-tests
然而,当我尝试在Dr. Racket中调试它时:
(debug)> (make-tests tests + (1 2 -> 3))
(debug)> tests
(#<procedure:+> ((1 2)) (3))
(debug)> all-tests
((#<procedure:+> ((1 2)) (3)))
因此,出于某种原因,在Dr. Racket v6.1中,我的代码在调试模式下工作,但在使用REPL时不起作用。发生了什么,我该如何调试我的代码?
答案 0 :(得分:2)
基于对this previous answer的评论:如果模块没有改变绑定,则不能从模块外部改变它。在REPL中运行代码与在模块中运行代码不同。 Racket语言中的球拍源是一个模块,#lang scheme
不是Scheme ,而是#lang racket
的同义词。
因此,要获得您希望的行为,可以将(define all-tests '())
替换为:
(define all-tests #f)
(set! all-tests '()) ; quick fix that makes all-test mutable
它会起作用。你也可以深入研究racket documentation about it。
答案 1 :(得分:1)
您可以取消选中Enforce constant definition
选项在DrRacket的“选择语言”菜单中的“动态属性”框中。
并作为你的宏的一个注释。为什么要为测试指定名称?该名称不会放在列表中,除了定义它以使其为all-tests
之外,它永远不会被使用。您可以改用let。当然,除非您稍后会对tests
做些什么。
(define-syntax make-tests
(syntax-rules (->)
[(_ function (args ... -> result) ...)
(let
((test (list function (list (list args ...) ...) (list result ...))))
(set! all-tests (cons test all-tests)))]))