user225700
user225700

Reputation: 11

LISP Find and Replace

I am currently tackling some beginner Lisp problems. I am using Common Lisp.

Below I have tried to implement a basic find and replace: char1 is the character to search for in the list, char2 is the character to replace it with and list-to-search is the list I am searching through.

(defun find-and-replace (char1 char2 list-to-search &optional (ammended-list(list)))
  (cond
   ((null list-to-search) ammended-list) 
   ((eql char1 (car list-to-search))
    (append ammended-list (list char2))
    (find-and-replace char1 char2 (cdr list-to-search)))
   (t (append ammended-list
              (list (car list-to-search))
              (find-and-replace char1 char2 (cdr list-to-search))))))

When I run:

(find-and-replace '1 'z '(1 2 3 1 4 5)) => (2 3 4 5)

Where as I would expect:

(z 2 3 z 4 5)

Upvotes: 0

Views: 699

Answers (2)

Barmar
Barmar

Reputation: 781096

append doesn't modify the argument list, you need to assign the result back to the variable. And you're not passing the amended list when you make the recursive calls, so it always uses the initial value nil.

(defun find-and-replace (char1 char2 list-to-search &optional (ammended-list(list)))
  (cond
   ((null list-to-search) ammended-list) 
   ((eql char1 (car list-to-search))
    (setq ammended-list (append ammended-list (list char2))
    (find-and-replace char1 char2 (cdr list-to-search) ammended-list))
   (t (setq ammended-list (append ammended-list (list char1))
      (find-and-replace char1 char2 (cdr list-to-search) ammended-list))))

This isn't the best way to write the function, though. APPEND is an expensive operation, it has to copy the list each time. Better is to build the new list one element at a time:

(defun find-and-replace(char1 char2 list-to-search)
  (cond ((null list-to-search) nil)
        ((eql char1 (car list-to-search))
         (cons char2 (find-and-replace char1 char2 (cdr list-to-search))))
        (t (cons (car list-to-search) (find-and-replace char1 char2 (cdr list-to-search))))))

Upvotes: 2

Rainer Joswig
Rainer Joswig

Reputation: 139261

Issues:

1 is a number. z is a symbol. Your code has nothing to do with characters, which are an actual datatype in Common Lisp.

Without proper formatting and indentation, Lisp programming gets extremely difficult.

The function append has no side effects.

append should be avoid, since it is expensive.

The lists your function can work with, are limited in length by the stack size due to the use of recursion. Typically on might use mapcar instead.

Upvotes: 4

Related Questions