2

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)

Rainer Joswig
  • 136,269
  • 10
  • 221
  • 346
Eduard Adrian
  • 95
  • 1
  • 12
  • 2
    "I get something with lambda expression as error message" -- please copy and paste the exact error message. – sds Dec 11 '17 at 18:32

1 Answers1

6

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))))))
sds
  • 58,617
  • 29
  • 161
  • 278
  • 1
    Hello,@sds. Thank you for your answer.But there is not any possible modification to my code to make it work? Our professor insisted to not work with standard library functions like 'subst'( yes,i know,it's a little bit weird,but i think she wants to make us understand the algorithm behind this......).Thank you for the helping links also :) – Eduard Adrian Dec 11 '17 at 19:01
  • @EduardAdrian: isn't `my-subst` what you are looking for? You can change the order of arguments, of course. Let me reiterate: if you are not using `car` and `cdr` symmetrically, you are not doing the right thing. – sds Dec 11 '17 at 19:17
  • It might be,but i don't understand the &key (test #'eql) and funcall structure. We are at a very basic level,i think we will learn about that later. That's why i asked for a very simplistic way of solving the exercise. – Eduard Adrian Dec 11 '17 at 19:25
  • @EduardAdrian: I added a simplified version. – sds Dec 11 '17 at 19:34