问题
I try to replace a certain element E in a list with another list K at all the main list levels.
(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)))))
Example:
(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)
I get something with lambda expression as error message.
Also,i tried instead of the listp(car l)
"block" :
((listp (car l)) (cons k (replaceList (cdr (car l)) e k)))
.
I get something weird :
(2 1 3 ( 6 1 7) 7 1 2 )
-> (2 (99 99) 3 (99 99) (99 99) 7)
回答1:
Error
Your "lambda expression message" is due to an extra set of parens around equal
in the listp
clause. Remember, Lisp parentheses are meaningful.
Use the standard library!
ANSI Common Lisp has subst which does what you want:
(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)
Your algorithm
Since you are operating on the tree, not list (you say "all the
main list levels"), you should treat car
and cdr
identically:
(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)
Or, simplified (without &key and funcall):
(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))))))
来源:https://stackoverflow.com/questions/47758839/lisp-replace-all-the-appereances-of-an-element-in-a-list