List 在Scheme中按位置合并两个列表 例子
第一个列表:List 在Scheme中按位置合并两个列表 例子,list,merge,tree,scheme,racket,continuation-passing,monad,List,Merge,Tree,Scheme,Racket,Continuation Passing,Monad,第一个列表:(1234) 第二个列表:(*slot(-slot(/slot-slot)) 输出:(*1(-2(/34))) 第一个列表的元素将插入到第二个列表中 第二个列表中的符号slot表示插入位置 我的解决方案 我已经编写了一个代码片段,它适用于上面的示例 (define (insert-slot numbers slots) (cond [(null? slots) '()] ;; operate on the nested list and come bac
(1234)
第二个列表:(*slot(-slot(/slot-slot))
输出:(*1(-2(/34)))
第一个列表的元素将插入到第二个列表中
第二个列表中的符号slot
表示插入位置
我的解决方案
我已经编写了一个代码片段,它适用于上面的示例
(define (insert-slot numbers slots)
(cond
[(null? slots)
'()]
;; operate on the nested list and come back to the element after
[(pair? (car slots))
(cons
(insert-slot numbers (car slots)) ;; nested list
(insert-slot numbers (cdr slots)))] ;; element after
;; insert number to slot
[(equal? (car slots) 'slot)
(cons (car numbers)
(insert-slot (cdr numbers) (cdr slots)))]
;; just take the original element in slots
(else
(cons (car slots)
(insert-slot numbers (cdr slots))))))
问题
但是,cond的第二个子句(对嵌套列表进行操作)存在一些问题,嵌套列表中使用的数字和后面的元素应该不同。后面的编号
是前面的编号
的结果。对于上面的示例,它是正确的,但是如果第二个列表像这样(*(+slot-slot)(-slot-slot))
,它将得到错误的答案
我发现我可以将状态存储在数字中
并根据调用的次数返回不同的值,但这与Scheme方式不同(没有额外存储的数据)。有没有简单的方法来解决这个问题;医生:是的,很时髦
非常有趣的问题!嵌套列表是一棵树,因此您正在将一个线性值列表合并到一棵树的边缘中,这取决于是否存在关键字“slot
所以我们开始,就像在结构递归任务中一样,遍历一棵树来创建它的一个精确副本,从而掌握它的窍门
(define (copy-tree tree)
(cond
[(not (pair? tree)) tree] ; return the leaf
[else (cons (copy-tree (car tree)) ; combine results from car
(copy-tree (cdr tree)))])) ; and results from cdr
接下来我们线性化它
然后我们遍历我们的状态,遍历给定值的列表以替换关键字的每个实例:
(define (merge-tree-fringe vals tree keywd k)
(cond
[(not (pair? tree)) ; for each leaf:
(if (not (eq? tree keywd)) ; if it is not the keyword,
(k vals tree) ; "return" vals AND leaf into k, or
(k (cdr vals) (car vals)))] ; USE the first of vals, if it is
[else
(merge-tree-fringe vals (car tree) keywd (lambda (Avals r) ; collect from car,
(merge-tree-fringe Avals (cdr tree) keywd (lambda (Dvals q) ; collect from cdr,
(k Dvals (cons r q))))))])) ; return the last vals and the combined results
我们称之为
> (merge-tree-fringe '(1 2 3 4)
'(* slot (- slot (/ slot slot)))
'slot
(lambda (v r) r))
'(* 1 (- 2 (/ 3 4)))
> (merge-tree-fringe '(1 2 3 4)
'(* (+ slot slot) (- slot slot))
'slot
(lambda (v r) r))
'(* (+ 1 2) (- 3 4))
这可以通过添加错误检查,并转换为具有较短名称和较少参数的内部定义来进一步解决
编辑:在模式匹配伪代码(可能更容易阅读/理解)中,它是
合并树边缘VAL树关键字=g VAL树(v r=>r)
哪里
g vals[a,…d]k=g vals a(avals r=>
g avals d(dvals q=>
k dvals[r,…q]))
g[v,…vs]lf k
|lf==keywd=k vs v——对匹配的叶使用第一个值
g vals lf k=k vals lf
这种在计算中穿行变化状态的计算模式正是(哈斯克尔的)状态单子的意义所在;上面的内容(不包括“树”类型的详细信息)如下所示:
merge_tree_borge vals tree keywd=evalState(g tree)vals
哪里
g(a:d)=do{r
> (merge-tree-fringe '(1 2 3 4)
'(* slot (- slot (/ slot slot)))
'slot
(lambda (v r) r))
'(* 1 (- 2 (/ 3 4)))
> (merge-tree-fringe '(1 2 3 4)
'(* (+ slot slot) (- slot slot))
'slot
(lambda (v r) r))
'(* (+ 1 2) (- 3 4))