我试图编写一个名为JOIN
的函数,它接受两个参数removesub*
。该函数需要返回第二个列表,并删除子序列的第一个出现。因此,如果第一个列表是(l1 and l2)
,则第一个'(a b c)
如果第二个列表被删除,则删除后删除的第一个a
和第一个b
移除a
后显示的c
- 无论原子嵌套的深度如何。
工作示例
输入:
b
输出:
(removesub* '(a b) '(w (x b) ((a) ((y z))) b a))
我当前的尝试似乎无法工作,因为我无法在嵌套递归调用之间共享l1参数,即(w (x b) (() ((y z))) a)
将l1拆分为两个单独的实例,从而产生以下结果。 如何共享((pair? (car l2)) (cons (removesub* l1 (car l2)) (removesub* l1 (cdr l2))))
值,以便每个递归调用都知道其他人是否在l1
找到了值的第一个实例?
工作示例
输入:
l1
输出:
(removesub* '(a b) '(w (x b) ((a) ((y z))) b a))
(w (x b) (() ((y z))) b)
答案 0 :(得分:1)
您需要传递结果符号以搜索下一次迭代。这有很多方法可以做到这一点。
您可以在帮助程序中使用复合返回
(define (removesub* elements-in-order haystack)
;; just use a pair to pass result and the
;; elements to continue searching for
(define (result eio h)
(cons eio h))
(cdr
(let rec ((eio elements-in-order)
(h haystack))
(cond ((or (not (pair? eio))
(not (pair? h)))
(result eio h))
((pair? (car h))
(let* ((r (rec eio (car h)))
(r2 (rec (car r) (cdr h))))
(result (car r2) (cons (cdr r) (cdr r2)))))
((eq? (car eio) (car h))
(rec (cdr eio) (cdr h)))
(else
(let ((r (rec eio (cdr h))))
(result (car r) (cons (car h) (cdr r)))))))))
注意我先做car
然后使用结果的两个部分来做下一个。
Scheme / Racket可以使用值
返回多个值(define (removesub* elements-in-order haystack)
(define (helper eio h)
(cond ((or (not (pair? eio))
(not (pair? h)))
(values eio h))
((pair? (car h))
(let*-values ([(eiocar hcar) (helper eio (car h))]
[(eiocdr hcdr) (helper eiocar (cdr h))])
(values eiocdr (cons hcar hcdr))))
((eq? (car eio) (car h))
(helper (cdr eio) (cdr h)))
(else
(let-values ([(eiocdr hcdr) (helper eio (cdr h))])
(values eiocdr (cons (car h) hcdr))))))
(let-values ([(eio result) (helper elements-in-order haystack)])
result))
与第一个语义相比并不是真正的语义差异,但它可能会更快一些,因为理论上结果可以保留在堆栈上而不是每个结果都必须创建一个可以像堆栈一样快速地进行GC编辑的缺点
您可以使用延续传递方式:
(define (removesub* elements-in-order haystack)
(let cps ((eio elements-in-order)
(h haystack)
(c (lambda (eio h) h)))
(cond ((or (not (pair? eio))
(not (pair? h)))
(c eio h))
((pair? (car h))
(cps eio
(car h)
(lambda (eio hcar)
(cps eio
(cdr h)
(lambda (eio hcdr)
(c eio (cons hcar hcdr)))))))
((eq? (car eio) (car h))
(cps (cdr eio) (cdr h) c))
(else
(cps eio
(cdr h)
(lambda (eio res)
(c eio (cons (car h) res))))))))
这个工作由助手有一个continuation参数。这与许多Scheme实现在运行之前对代码实际做的很接近。
您可以使用变异
可能是最快最简单的,但是您需要使用#!r6rs
或其他标准Scheme而不是#!racket
作为实现语言。