方案 - 函数递归错误

Scheme - Function recursion error

此函数读取列表并交换值,但前提是散列 table 中存在与列表中的元素匹配的键。但是,读入的列表可能包含其他列表,我想递归地检查它。我使用 if (list? elementInList) 来确定我是否正在处理一个列表,因此我可以使用递归调用在该列表中搜索可能需要交换的元素。我试图这样做,但它没有正确处理列表中的列表。我究竟做错了什么?

(define (let-helper L)
    (map (lambda (x) (swap x (hash-ref *variable-table* x) L))
         (filter (lambda (x) 
                     (if (list? x)
                         (let-helper x) ;; recursion here
                         (hash-has-key? *variable-table* x)))
                 L)))

我建议只 flatten 编辑列表,以便您可以继续使用 mapfilter,如下所示:

(define (let-helper L)
  (map (lambda (x) (swap x (hash-ref *variable-table* x) L))
       (filter (lambda (x) (hash-has-key? *variable-table* x))
               (flatten L))))

否则要让它工作,需要在没有 mapfilter 的情况下编写它,如下所示:

(define (let-helper L)
  (let ((action (lambda (x) (swap x (hash-ref *variable-table* x) L)))
        (predicate (lambda (x) (hash-has-key? *variable-table* x))))

    (let loop ((a '()) (L L))
      (if (null? L)
          (reverse a)
          (if (list? (car L))
              (loop (cons (let-helper (car L)) a) (cdr L))
              (if (predicate (car L))
                  (loop (cons (action (car L)) a) (cdr L))
                  (loop a (cdr L))))))

未测试。


所以只有当散列有键时才应该发生交换,但返回的列表应该仍然有没有交换的元素?如果是这样,那么不从列表中删除元素不是键将解决这个问题:

(define (let-helper L)
  (map (lambda (x) 
         (if (list? x) 
             (let-helper x) 
             (if (hash-has-key? *variable-table* x) 
                 (swap x (hash-ref *variable-table* x) L) 
                 x))))
       L)

(define (let-helper L)
  (let ((action (lambda (x) (swap x (hash-ref *variable-table* x) L)))
        (predicate (lambda (x) (hash-has-key? *variable-table* x))))

    (let loop ((a '()) (L L))
      (if (null? L)
          (reverse a)
          (if (list? (car L))
              (loop (cons (let-helper (car L)) a) (cdr L))
              (if (predicate (car L))
                  (loop (cons (action (car L)) a) (cdr L))
                  (loop (cons (car L) a) (cdr L))))))