Ответ 1
loop от cl-macs.el имеет поддержку для разрушения, как CL:
(loop for (key . value) in my-list
collect (cons value key))
Какой лучший способ перебрать alist и сделать что-то с каждой парой в Emacs Lisp? Я полагаю, что макрос не будет сложным, мне просто интересно, построено ли это где-то. Есть ли более элегантный способ, чем ниже?
(setq my-list '((a . 1)
(b . 2)
(c . 3)))
(loop for key in (mapcar 'car my-list)
for value in (mapcar 'cdr my-list)
collect (cons value key))
;; Returns this
((1 . a)
(2 . b)
(3 . c))
loop от cl-macs.el имеет поддержку для разрушения, как CL:
(loop for (key . value) in my-list
collect (cons value key))
Другим способом сделать это без loop
является mapcar
и лямбда. Я не думаю, что это более элегантно, но это более идиоматично для elisp, а не Common Lisp:
(mapcar (lambda (element)
(let ((key (car element))
(value (cdr element)))
(cons value key)))
'((1 . a) (2 . b)))
Не понятно, что именно вы хотите сделать - вопрос очень общий. Есть много способов перебрать alist и действовать на некоторые или все его записи. Вы сами показываете один путь. Посмотрите также на while
и, в частности, dolist
. Это ваш пример с помощью dolist
:
(let ((res ())) (dolist (x my-list) (push (cons (cdr x) (car x)) res)) (nreverse res))
(Возможно, лучший способ использовать loop
, чем в вашем примере, - нет необходимости создавать три списка (два mapcar
+ loop
), например.)
dash.el
предоставляет множество функций управления списком, таких как maps. Те, которые принимают функции в качестве аргументов, также имеют anaphoric. Это позволяет использовать краткий functional код. dash.el
функции начинаются с тире, поэтому имя и анафорические версии начинаются с двух тире. Итак, вариант ателора выглядел бы намного лучше:
(--map (cons (cdr it) (car it)) '((1 . a) (2 . b))) ; ((a . 1) (b . 2))