3

我现在正在学习 R5RS Scheme(来自 PocketScheme),我发现我可以使用一个内置在 Scheme 的某些变体中但不是全部的函数:追加!

换句话说 - 破坏性地更改列表。

我对实际代码的兴趣不如对答案的兴趣,而是对将列表作为函数(或向量或字符串)传递然后对其进行变异的过程感兴趣。

例子:

(define (append! lst var)
    (cons (lst var))
)

当我使用上述方法时,我必须做一些(define list (append! foo (bar))我想要更通用的事情。

4

2 回答 2

5

突变,虽然允许,但在 Scheme 中强烈反对。PLT 甚至删除了set-car!and set-cdr!(尽管他们用set-mcar!and替换了它们set-mcdr!)。然而,一个规范append!出现在SRFI-1中。这append!和你的有点不同。在 SRFI 中,实现可以不需要修改 cons 单元以附加列表。

如果你想要一个append!保证改变被附加到的列表的结构,你可能必须自己编写它。这并不难:

(define (my-append! a b)
  (if (null? (cdr a))
      (set-cdr! a b)
      (my-append! (cdr a) b)))

为了使定义简单,这里没有错误检查,但很明显,您需要传入长度至少为 1 的列表 asa和(最好)一个(任意长度的)列表 as b。原因a必须至少为长度 1 是因为您不能set-cdr!在空列表中。

既然你对它的工作原理感兴趣,我会看看我是否能解释一下。基本上,我们想要做的是沿着列表向下a直到我们到达最后cons一对,即(<last element> . null). 所以我们首先a通过nullcdr. 如果是,我们将set-cdr!其设置为我们要附加的列表,我们就完成了。如果没有,我们必须my-append!调用cdrof a。每次我们这样做时,我们都会接近a. 由于这是一个变异操作,我们不会返回任何东西,所以我们不需要担心将修改后的列表形成为返回值。

于 2009-07-03T18:07:05.953 回答
0

在这个话题上投入 2-3 美分,迟到总比没有好……

(1)在Scheme中使用破坏性程序没有错,对正在修改的结构只有一个引用。因此,例如,通过单个引用有效地、零碎地构建一个大型列表 - 并且在完成后,使该列表(现在可能不会被修改)从各种引用中得知和引用。

(2) 我想追加!应该表现得像 APPEND,只是(可能)具有破坏性。所以追加!应该期望任意数量的列表作为参数。除了最后一个列表之外,每个列表都可能是 SET-CDR!'d 到下一个。

(3) APPEND的上述定义!本质上是来自 Mac Lisp 和 Common Lisp 的 NCONC。(和其他口齿不清)。

于 2011-03-12T03:51:48.070 回答