Guile Scheme 中经历的一件非常迷惑的事情。。。

我想创建一个list,用一个指针一直指向列表尾部,以用来添加元素。

但是不知道为什么除了 ‘(3) 这样的赋值以外,都会出现上图这种诡异的情况。。。还把repl给我炸了好几次。。。

更新:

反转了,终端中直接运行guile的repl没有问题,但是geiser里面仍然还有问题

图片

图片

没跑过guile, 用MSYS64自带的guile 2.2.7 试了一下, 更迷惑了。。。。。。

应该是 guile3 的 pretty-print 模块有联系,两段代码一个用 pretty-print,另一个用纯朴的 display,然后用guile3 < file.scm 来执行

这段会导致 tp 指向随机的东西

(use-modules (ice-9 pretty-print))
(define tl '(1 2))
(define tp (cdr tl))
(set-cdr! tp (cons 3 '()))
  (pretty-print tl)
  (pretty-print tp)

这段会稳定地输出期待的 (1 2 3) (3)

(define tl '(1 2))
(define tp (cdr tl))
(set-cdr! tp (cons 3 '()))
  (display tl) (newline)
  (display tp) (newline)

Guile 的 pretty-print 可能有 bug。

一个 workaround 是把一开始的

(define tl '(1 2))

改成

(define tl (list 1 2))

也就是用 (list 替换 (quote,然后 pretty-print 就正常了,

1 个赞

不要对 quoted constant 如 '(1 2 3) 使用含有副作用的操作(如set-cdr!),因为他们可能放在只读内存内。如果需要副作用操作,用 list 代替 quote

3 个赞

啊, 我一直以为它们是一样的。。。方便给个官方或者详细解释的参考链接吗?

R7RS标准 4.1.2 节中明确说了,quote 返回的值是常量,试图修改常量是错误的。

这事情是这样的:

R5RS 和 R7RS 里同一节都说了 “it is an error to alter a constant (i.e. the value of a literal expression) using a mutation pro- cedure like set-car! or string-set!.”,但 R6RS 没说。

Guile 先支持的 R5RS。R7RS 和 R6RS 是部分支持。

只支持 R6RS 的 Chez 就没这类问题。

2 个赞

谢谢, 学习到了 :heart_eyes: