Вопрос
Я хотел бы сделать:
(mapcar #'assoc '(a s) '((a . b) (c . d) (s . f)))
И вернись
((A . B) (S . F))
Что кажется довольно разумным, учитывая (assoc 'a '((a . b) (c . d) (s . f)))
возврат (A . B)
а также (assoc 's '((a . b) (c . d) (s . f)))
возврат (S . F)
. Анкет Но, увы, это не работает:
*** - ASSOC: A is not a list
The following restarts are available:
ABORT :R1 Abort main loop
Какие-нибудь мысли?
Решение
При использовании с двумя списками, mapcar
Применяет функцию парных по спискам (и с тремя списками, это применяет их в тройной повод и т. Д.). Так
(mapcar #'assoc '(a s) '((a . b) (c . d) (s . f)))
такой же как
( (assoc 'a (a . b)) (assoc 's (c . d)) )
(При использовании со списками различной длины, mapcar
использует размер самый маленький список). Чтобы получить то, что вы хотите, вы должны сделать:
(mapcar (lambda (x) (assoc x '((a . b) (c . d) (s . f)))) '(a s))
Другие советы
Нам нужен другой уровень списка. Второй аргумент должен быть списком списков ассоциации.
CL-USER > (mapcar #'assoc '(a s) '(((a . b) (c . d) (s . f))))
((A . B))
Но второй аргумент - только один элемент длиной. Теперь мы можем использовать трюк и сделать его круговым списком:
CL-USER > (mapcar #'assoc '(a s) '#1=(((A . B) (C . D) (S . F)) . #1#))
((A . B) (S . F))
Если мы построим круговой список для второго аргумента, то он работает.
Как функция:
(defun circular (list)
(if (null list)
list
(setf (cdr (last list)) list)))
CL-USER > (mapcar #'assoc '(a s) (circular '(((a . b) (c . d) (s . f)))))
((A . B) (S . F))