Я бы не писал эту функцию, потому что Райнер Йосвиг говорит , стандарт уже обеспечивает SET-DIFFERENCE
. Тем не менее, если бы мне пришлось предоставить реализацию функции, я бы использовал ее:
(defun filter (a b)
(let ((table (make-hash-table)))
(map 'nil (lambda (e) (setf (gethash e table) t)) a)
(remove-if (lambda (e) (gethash e table)) b)))
Делая это таким образом, вы получаете несколько преимуществ, наиболее важным из которых является то, что он проходит только b
один раз; использование хеш-таблицы для отслеживания того, какие элементы находятся в a
, вероятно, будет работать намного лучше, если a
длинный.
Кроме того, использование общих функций последовательности, таких как MAP
и REMOVE-IF
, означает, что эта функция может использоваться со строками и векторами, а также со списками, что является преимуществом даже по сравнению со стандартной функцией SET-DIFFERENCE
. Основным недостатком этого подхода является то, что если вы хотите расширить функцию с помощью аргумента :TEST
, который позволяет пользователю предоставлять предикат равенства, отличный от значения по умолчанию EQL
, поскольку хеш-таблицы CL работают только с небольшим числом предварительно определенные предикаты равенства (точнее, EQ
, EQL
, EQUAL
и EQUALP
).