跟踪改变汽车/集车!行为

时间:2017-05-01 15:09:45

标签: scheme

我发现了一些非常令人困惑的行为,我怀疑这是我的Scheme解释器中的一个错误,但经验告诉我,我几乎肯定是不正确的。我正在使用Petite Chez Scheme,版本9.4.1。

(let ((a '(0))) (set-car! a 9) (car a))

在我的解释器上,此代码返回0而不是9。更令人困惑的是,如果我跑

(trace car)
(untrace car)
(let ((a '(0))) (set-car! a 9) (car a))

我得到9,这是我首先想到的。地球上到底发生了什么?范围和指针有什么奇怪的事吗?我应该将此作为错误提交吗?

2 个答案:

答案 0 :(得分:2)

原因是您正在修改绑定到 costant a的{​​{1}}。根据特定的解释器/编译器,此操作未定义(例如,在其他实现中,返回的值为9)。

相反,通过修改使用'(0)运算符构建的值,可以在任何实现中正确执行操作,包括Petite Chez Scheme:

list

答案 1 :(得分:1)

原因是这是无效的Scheme代码。根据报告(所有这些),您正在改变文字数据。想象一下这个例子在R5RS:

app.get('/', function(req, res) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    var clubs = fs.createReadStream(__dirname + '/html/clubs.html')
    clubs.pipe(res);
});

正如您所看到的,程序已经发现您使用文字列表(define test '(1 2 3)) (define (get-some-list) '(1 2 3)) (set-car! test 5) (gen-some-list) ; ==> (5 2 3) 两次,因为您不允许更改它们,因为它们是相同的,因此它们使用相同的对象来优化它。使用(1 2 3)作为R5RS,可选择发出错误信号,不做任何事情或实际更新文字数据。未定义它取决于实施者。实际上,评估set-car!和获得test也是完全可以的。

在R6RS中,它应该引发&断言异常 according to the report

(1 2 3)

这告诉你两件事。让函数返回不可变数据不会放弃规则,并且执行任何这些操作也应该引发&断言异常:

#!r6rs
(import (rnrs)
        (rnrs mutable-pairs))

(define (g) '(constant-list))
(set-car! (g) 3) ⇒  unspecified
; should raise  &assertion exception

与您的问题中的代码相同的有效方案:

(set-car! '(constant-list) 3) ⇒  unspecified
; should raise  &assertion exception

(define const '(constant-list))
(set-car! const 3) ⇒  unspecified
; should raise  &assertion exception