是否可以在Scheme中创建一个没有变异的循环数据结构?

时间:2018-04-01 20:20:09

标签: functional-programming scheme reference-counting

我可以在Scheme中创建一个循环数据结构,如下所示:

(define my-pair (cons 1 1))
(set-car! my-pair my-pair)

是否可以在Scheme中创建循环数据结构而不使用变异? (我正在准备关于引用计数限制的讲座。)

3 个答案:

答案 0 :(得分:5)

您可以使用闭包创建一个惰性列表:

; The infinite list (1 1 1 ...
(define ones
  (letrec ((x (cons 1 (lambda () x))))
    x))

> ones
'(1 . #<procedure>)
> ((cdr ones))
'(1 . #<procedure>)

验证循环的身份检查:

> (eq? ones ((cdr ones)))
#t

答案 1 :(得分:3)

通过关注相关问题(Why don't purely functional languages use reference counting?)的链接,我看到了对letrec的引用。这让我意识到我确实可以创建一个循环的数据结构&#34;在Scheme中:

(letrec ((add (lambda (x y) (if (>= x y) (+ x y) (add2 y x))))
         (add2 (lambda (x y) (if (>= x y) (+ x y) (add y x)))))
  (add 1 5))

答案 2 :(得分:1)

添加到@molbdnilo 回答大多数方案 imeplemetation 定义 delayforce, 允许创建所谓的流(定义在 SICP).

; The infinite list (1 1 1 ...
(define ones (cons 1 (delay ones)))

> ones
(1 . #<promise>)

> (force (cdr ones))
(1 . #<promise>)

(eq? ones (force (cdr ones)))
#t

delayforce 可以实现为只是 lambda 表达式的宏。您甚至可以编写处理流的过滤器或映射等过程。

编辑:

同样由 R7RS 定义,您可以创建带有基准标签的真实圆形列表。

(define x '#0=(a b c . #0#))
x
;; ==> #0=(a b c . #0#)
(eq? x (cdddr x))
#t

如果 Scheme 完全支持 R7RS 规范,它应该允许以相同的方式定义和显示循环列表。请注意,在 Kawa Scheme 中,它将循环打印以显示您需要使用 (write x) 的循环列表。