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))