0
votes

So I am learning Lisp at school and one of the programs I have to create is one that duplicates the functionality of remove-if-not by using mapcan. I have created the program and it works correctly but I don't understand the output.

Specifically, if I were to run:

(findall 'numberp '(1 a 3))

The output is: (1 3)

The program is the following:

(defun findAll (fct l)
(cond
        ((null l) nil)
        ((mapcan (lambda(x) (if (funcall fct x) (list x) nil )) l))
    )
)

My understanding of the solution is the following: "For each of the elements of the list l call the lambda function. If the result of the function fit and the element x returns true, then return the element surrounded by parentheses, otherwise return nil"

What specifically I am not understanding is how a series of consecutive calls to "list(x)" will in the end return a list of atoms such as (1 2).

1

1 Answers

6
votes

Not sure why you have tagged your question SLIME, which is an IDE.

Let's format and indent your code readable.

(defun findAll (fct l)
  (cond
   ((null l) nil)
   ((mapcan (lambda (x)
              (if (funcall fct x)
                  (list x)
                nil))
            l))))

It's possible to write it that way, but usually we have a T condition to make clear that the last clause is always called.

(defun findAll (fct l)
  (cond
   ((null l) nil)
   (t (mapcan (lambda (x)
                (if (funcall fct x)
                    (list x)
                  nil))
              l))))

Since MAPCAN already deals with empty lists, you can just delete the COND and the first clause. findAll is typically named as find-all.

(defun find-all (fn list)
  (mapcan (lambda (item)
            (if (funcall fn item)
                (list item)
              nil))
          list))

For each of the elements of the list l call the lambda function. If the result of the function fit and the element x returns true, then return the element surrounded by parentheses, otherwise return nil

For each of the elements of the list LIST call the lambda function. If the result of the function FN and the element ITEM returns true, then return a list of just the ITEM, otherwise return the empty list. The end result is the (destructively) appended list of all result lists of the lambda function.