2009-08-12 6 views
5

Я начинаю писать мне Common Lisp, и я просто собираюсь объединять вещи и форматировать их.Как я могу форматировать alist в общем lisp?

Давайте предположим, что у меня есть ассоциативный список, как это:

(defvar *map* '((0 . "zero") (1 . "one") (2 . "two"))) 

Как отформатировать его, как это?

0: zero 
1: one 
2: two 

я что-то вроде (format t "~{~{~a: ~a~}~%~}" *map*) думать, но это дает ошибку, потому что «ноль» не список, и вы не можете взять машину из него.

Конечно, делать (format t "~{~a~%~}" *map*) отпечатки

(0 . "zero") 
(1 . "one") 
(2 . "two") 

, как это положено, но это не совсем то, что я хочу. Есть ли лучший способ сделать это, чем просто (dolist (entry *mapping*) (format t "~a: ~a~%" (car entry) (cdr entry)))?

ответ

10

# сла-садоводы канал на Freenode предлагает делать привязку петли деструктурирующей так:

(loop for (a . b) in *mapping* 
    do (format t "~a: ~a" a b)) 
1

Я не думаю, что есть лучший способ сделать это; Я бы использовал map():

(format t "~{~a~%~}" 
    (map 'list 
    #'(lambda (entry) 
     (format nil "~a: ~a" (car entry) (cdr entry)) 
    *map*)) 
+0

MAPCAR больше к точке ... – skypher

6

Вы правы, в том, что он не похож есть ли способ, чтобы выбрать обособленно ячейку минусы от FORMAT.

Если определить другую функцию для форматирования единой ассоциации:

(defun print-assoc (stream arg colonp atsignp) 
    (format stream "~A: ~A" (car arg) (cdr arg))) 

, то это легко:

(format t "~{~/print-assoc/~%~}" *map*) 

Я не уверен, если это улучшение или нет. С одной стороны, это немного сложнее, но, с другой стороны, он вырывает print-assoc в функцию (многоразовую), что может быть полезно.

+6

Вы должны использовать квалифицированные имена функций в формате. FORMAT анализирует указанный символ в * пакете *, и вы никогда не узнаете, что такое * пакет * во время вызова формата. –

4

Я думаю, что вынос урок здесь действительно не использовать пунктирные списки для alists. Вы сохраняете одну ячейку cons, конечно, но вы отказываетесь от всех хороших функций последовательности и списка. Это просто не стоит. Ваше форматирование пример тривиален с полностью сформированными списками:

(defvar *map* '((0 "zero") (1 "one") (2 "two"))) 
(format t "~:{~a: ~a~}" *map*) 
1

Преобразования ALIST клетки (a . 2) в список (a 2) с помощью

(mapcar #'(lambda (x) `(,(car x) ,(cdr x))) *map*) 

, а затем процесс в формате.

Для например., Для печати ((a . 2) (b . 3)) в "a=2&b=3"

использование

(format t "~{~{~a~^=~}~^&~}" (mapcar #'(lambda (x) `(,(car x) ,(cdr x))) *map*))