我发现了一些非常令人困惑的行为,我怀疑这是我的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
,这是我首先想到的。地球上到底发生了什么?范围和指针有什么奇怪的事吗?我应该将此作为错误提交吗?
答案 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