Lisp - 替换列表中

时间:2017-12-11 18:10:24

标签: syntax-error lisp common-lisp

我尝试将列表中的某个元素E替换为所有主列表级别的另一个列表K.

(defun replaceList(l e k)
  (cond
    ((null l) nil)
    ((equal e (car l)) (cons k (replaceList (cdr l) e k)))
    ((listp (car l))
     ((equal e (car (car l))) (cons k (replaceList (cdr (car l)) e k))))
    (t (cons (car l) (replaceList (cdr l) e k)))))

示例:

(replaceList '(3 1 2 (6 1) 7 (5 (5 (3 1))) 9) '1 '(99 99))
--> (3 (99 99) 2 (6 (99 99)) 7 (5 (5 (3 (99 99) ) ) ) 9)

我得到一些lambda表达式作为错误消息。

另外,我试过而不是listp(car l)"阻止" : ((listp (car l)) (cons k (replaceList (cdr (car l)) e k)))。 我得到一些奇怪的东西: (2 1 3 ( 6 1 7) 7 1 2 ) - > (2 (99 99) 3 (99 99) (99 99) 7)

1 个答案:

答案 0 :(得分:6)

错误

你的" lambda表达消息"是由于equal子句中listp周围有一组额外的parens。请记住,Lisp parentheses are meaningful

使用标准库!

ANSI Common Lisp subst可以满足您的需求:

(subst '(99 99) 1 '(3 1 2 (6 1) 7 (5 (5 (3 1))) 9) :test #'equal)
==> (3 (99 99) 2 (6 (99 99)) 7 (5 (5 (3 (99 99)))) 9)

您的算法

由于您在上操作,而不是列表(您说" 所有 主要列表级别"),您应该同等对待carcdr

(defun my-subst (new old tree &key (test #'eql))
  (cond ((funcall test old tree)
         new)
        ((atom tree)
         tree)
        (t
         (cons (my-subst new old (car tree) :test test)
               (my-subst new old (cdr tree) :test test)))))
(my-subst '(99 99) 1 '(3 1 2 (6 1) 7 (5 (5 (3 1))) 9) :test #'equal)
==> (3 (99 99) 2 (6 (99 99)) 7 (5 (5 (3 (99 99)))) 9)

或者,简化(没有&keyfuncall):

(defun my-subst (new old tree)
  (cond ((equal old tree)
         new)
        ((atom tree)
         tree)
        (t
         (cons (my-subst new old (car tree))
               (my-subst new old (cdr tree))))))