附加!在Scheme?

时间:2009-07-03 17:58:26

标签: scheme append

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

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

我对实际代码并不是那么感兴趣,只要理解一个人可以将列表作为函数(或向量或字符串)传递然后改变它的过程。

示例:

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

当我使用上述方法时,我必须执行类似(define list (append! foo (bar))的操作,我希望这些更通用。

2 个答案:

答案 0 :(得分:5)

虽然允许变异,但在计划中强烈反对。 PLT甚至删除了set-car!set-cdr!(尽管他们用set-mcar!set-mcdr!“替换”了它们。但是,append!中出现append!的规范。这个append!与你的有点不同。在SRFI中,实现可能,但不是必需来修改缺点单元以附加列表。

如果您想要保证(define (my-append! a b) (if (null? (cdr a)) (set-cdr! a b) (my-append! (cdr a) b))) 来更改要附加到的列表的结构,您可能需要自己编写。这并不难:

a

为了保持定义简单,这里没有错误检查,但很明显,你需要传递一个长度至少为1 b的列表,并且(最好)一个列表(任意长度) )aset-cdr!必须至少为长度1的原因是因为您无法在空列表中a

既然你对它的工作方式感兴趣,我会看看能不能解释一下。基本上,我们要做的是在列表cons下方,直到我们到达最后一个(<last element> . null)对,即a。因此,我们首先通过检查null中的cdr来查看set-cdr!是否已经是列表中的最后一个元素。如果是,我们使用my-append!将其设置为我们要添加的列表,我们就完成了。如果没有,我们必须在cdr a上致电a。每次我们这样做,我们都会接近{{1}}的末尾。由于这是一个变异操作,我们不会返回任何内容,因此我们不必担心将修改后的列表形成为返回值。

答案 1 :(得分:0)

在这个主题上投入2-3美分,总比迟到总好......

(1)使用Scheme 中的破坏性过程没有任何问题,而只有一个对被修改结构的引用。例如,通过单个引用有效地构建大型列表 - 并且在完成时,使得(现在可能不被修改)列表已知并从各种指示对象中引用。

(2)我认为APPEND!应该像APPEND一样,只是(可能)具有破坏性。 APPEND!应该期望任意数量的列表作为参数。每个列表,但最后一个列表可能是SET-CDR!'到下一个。

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