Search code examples
lambdafunctional-programminglispcommon-lisp

Lisp Lambda function with IF clause


I am trying to make a "Replace each occurence of x with y in list l" function with only mapcar and a lambda function.

I guess that the lambda function will check if an entry equals to "x" and replace it with "y". But the lambda function doesn't seem to accept IF or conditional statements, is there any proper way to do this?

(defun remplacee(x y l)
    (mapcar #'(lambda(c)((IF (EQ c x) y x))) l)
    )

Solution

  • Use standard formatting (see e. g. Practical Common Lisp).

    (defun remplacee (x y l)
      (mapcar #'(lambda (c)
                  ((if (eq c x) y x)))
              l))
    

    Use correct spelling. Since replace is already part of the standard, we'll use some placeholder prefix, e. g. my-.

    (defun my-replace (x y l)
      (mapcar #'(lambda (c)
                  ((if (eq c x) y x)))
              l))
    

    The form ((if (eq c x) y x)) is not valid here. The first item of an evaluated list must be a function designator: either a symbol naming a function, or a lambda form (i. e. a list starting with the symbol lambda). The first item here is neither.

    What you obviously meant was (if (eq c x) y x), i. e., the inner form not wrapped in another list.

    (defun my-replace (x y l)
      (mapcar #'(lambda (c)
                  (if (eq c x) y x))
              l))
    

    This almost works, but it uses eq, which compares only by object identity. This is usually not general enough, except for comparing interned symbols or keywords. The usual default comparison function is eql.

    (defun my-replace (x y l)
      (mapcar #'(lambda (c)
                  (if (eql c x) y x))
              l))
    

    I'd recommend using more descriptive names:

    (defun my-replace (item with list)
      (mapcar #'(lambda (c)
                  (if (eql c item) with item))
              list))
    

    Optionally, it can make sense to allow different comparators:

    (defun my-replace (item with list &key (test #'eql))
      (mapcar #'(lambda (c)
                  (if (funcall test c item) with item))
              list))