Drracket中调试和REPL模式之间的不同行为:修改常量

时间:2014-09-25 15:44:36

标签: debugging scheme racket

我正在尝试在方案中编写自己的单元测试库。到目前为止,我在定义窗口中有以下代码:

#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时不起作用。发生了什么,我该如何调试我的代码?

2 个答案:

答案 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)))]))