LISP избавляет от надоедливых NILs - PullRequest
1 голос
/ 21 февраля 2012

У меня есть следующая функция фильтра, которая отфильтровывает список x, который не удовлетворяет функции f.

Например, я звоню (filter 'evenp '(0 1 2 3)) и возвращаюсь (NIL 1 NIL 3). Но это именно моя проблема. Как мне сделать так, чтобы я просто вернулся (1 3)?

(defun filter (f x)
    (setq h (mapcar #'(lambda (x1)
                        (funcall f x1))
                    x))
    (mapcar #'(lambda (a b)
                (cond ((null a) b)))
            h x))

т.е. проблема вот в чем: (lambda (a b) (cond ( (null a) b) ) ) В моем cond у меня нет t или другого оператора, так почему бы просто не остановиться и не вернуть nil? Как сделать так, чтобы он ничего не «возвращал», даже nil, если (cond ( (null a) b) ) не удовлетворен?

Очень ценится. :)

Ответы [ 3 ]

3 голосов
/ 21 февраля 2012

На основании этот вопрос будет:

(remove-if #'evenp '(0 1 2 3))
1 голос
/ 21 февраля 2012

Чтобы ответить на более общий вопрос о том, как разделить произвольное количество элементов (включая ни одного вообще) на результат, mapcan (семантически mapcar + append)полезно для этого:

(defun filter (f xs)
  (mapcan (lambda (x)
            (if (funcall f x)
                (list x)
                nil))
          xs))

mapcan также полезно, если вы хотите сопоставить элемент с несколькими результатами:

(defun multi-numbers (xs)
  (mapcan (lambda (x) (list x (+ x x) (* x x))) xs))

(multi-numbers (list 1 2 3))
;=> (1 2 1 2 4 4 3 6 9)
1 голос
/ 21 февраля 2012

Игнорируя другие вопросы, поднятые в этом посте, я скажу, что mapcar всегда будет возвращать что-то для каждой вещи, которую он отображает, поэтому вы не можете использовать другую mapcar для очистки там NIL. Это то, что делает mapcar - он просматривает элемент (или элементы, если отображается в нескольких списках, как ваша вторая попытка mapcar) и собирает результат вызова некоторой функции с этими аргументами.

Вместо этого, в этой ситуации, если вам по какой-то причине пришлось использовать mapcar, и вы не хотели использовать NIL, вы могли бы использовать функцию remove, т.е. (remove nil (mapcar ...))

Поскольку ответ @ stark опубликован выше, я скажу, что функция remove-if - это, по сути, то, что вы пытаетесь реализовать здесь. (Вот где вопрос о том, подходит ли это для домашней работы или нет, становится наиболее актуальным.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...