我现在正在学习R5RS计划(来自PocketScheme),我发现我可以使用内置于Scheme的某些变体中的函数但不是全部:附加!
换句话说 - 破坏性地改变列表.
我对实际代码不是那么感兴趣,而是理解一个人可以将列表作为函数(或向量或字符串)传递然后改变它的过程.
例:
(define (append! lst var)
(cons (lst var))
)
Run Code Online (Sandbox Code Playgroud)
当我使用上面的方法时,我必须做一些(define list (append! foo (bar))我想要更通用的东西.
虽然允许变异,但在计划中强烈反对.PLT甚至到目前为止,以去除去set-car!和set-cdr!(虽然他们用"替换为"他们set-mcar!和set-mcdr!).但是,SRFI-1中append!出现了一个规范.这与你的有点不同.在SRFI中,实现可以但不是必须修改cons单元以附加列表.append!
如果你想有一个append!是保证要变更被附加到列表中的结构,你可能不得不自己编写.这并不难:
(define (my-append! a b)
(if (null? (cdr a))
(set-cdr! a b)
(my-append! (cdr a) b)))
Run Code Online (Sandbox Code Playgroud)
为了保持清晰简单,没有错误检查在这里,但很明显,你将需要在长的列表,通过至少为1 a,和(最好)一个(任意长度的)列表作为b.原因a必须至少是长度1是因为你不能set-cdr!在空列表中.
既然你对它的工作方式感兴趣,我会看看能不能解释一下.基本上,我们想要做的是沿着列表向下,a直到我们到达最后cons一对,即(<last element> . null).所以,我们首先看是否a已经在列表中的最后一个元素通过检查null的cdr.如果是,我们set-cdr!会将其设置为我们附加的列表,并且我们已经完成了.如果没有,我们要调用my-append!上cdr的a.每次我们这样做,我们接近结束a.由于这是一个变异操作,我们不会返回任何内容,因此我们不必担心将修改后的列表形成为返回值.