How to use MAPCAR to implement REMOVE-IF

How can I use the MAPCAR function to implement a function equivalent to REMOVE-IF , non-recursive in Common Lisp?

+4
source share
1 answer

This is not possible in MAPCAR because it always returns a list of the same length as the input (and you need a shorter list if some of the input elements satisfy the predicate.)

But this is possible using the associated MAPCAN function. If you

  • Apply a predicate to each element of X
    • If X satisfies the predicate, replace (X)
    • If X does not satisfy the predicate, replace NIL
  • Combining Result Lists

then you will have a list containing items that did not satisfy the predicate, as needed.

MAPCAN will combine these operations with a given function that implements step # 1.

Example:

 (defun list-if-not (pred) (lambda (x) (if (funcall pred x) nil (list x)))) (defun my-remove-if (pred lst) (mapcan (list-if-not pred) lst)) (my-remove-if #'evenp '(1 2 3 4 5)) 

==> (1 3 5)

MAPCAR cannot do this, although you can combine it with NCONC (or APPEND ) for the same result:

 (defun my-remove-if (pred lst) (apply #'nconc (mapcar (list-if-not pred) lst))) 
+4
source

Source: https://habr.com/ru/post/1444510/


All Articles