Как и у любого инструмента format
, есть свои ограничения, и он не очень хорошо подходит для таких задач.Вероятно, лучшее, что вы можете получить в простом формате, не прибегая к уловкам черной магии с ~?
или ~/
, которые вы или кто-либо еще, вероятно, не поймете в будущем, это код:
CL-USER> (format t "~{~{~A ~}~%~}"
'((X X X) (X X X X X X) (X X X X X X X X X)))
X X X
X X X X X X
X X X X X X X X X
Если вы хотите получить сложную структуру вывода, попробуйте выполнить некоторую предварительную обработку.Например, если формат списка жестко запрограммирован, вы можете использовать это:
(format t "~{~{~6A~} ~%~}"
(mapcar (lambda (l)
(loop :for i :from 0 :to (1- (length l)) :by (/ (length l) 3)
:collect (format nil "~{~A ~}"
(subseq l i (+ i (/ (length l) 3))))))
'((X X X) (X X X X X X) (X X X X X X X X X))))
Здесь мы сначала собираем элементы списка в одинаковое количество групп для каждого списка, печатаем их и такполучить 3 списка с одинаковым количеством элементов, которые затем можно обработать с помощью format
.
Подробнее о format
вы можете узнать в соответствующей главе превосходной книги Лиспа Питера Сейбела: http://gigamonkeys.com/book/a-few-format-recipes.html
РЕДАКТИРОВАТЬ
Если у вас есть переменное количество списков, каждый из которых в два раза больше предыдущего, вам также необходимо заранее подготовить строку формата:
CL-USER> (defun format-custom-list (list)
(format t (format nil "~~{~~{~~~DA~~} ~~%~~}" (* 2 (length list)))
(mapcar (lambda (l)
(let* ((len (length l))
(len/3 (/ len 3)))
(loop :for i :from 0 :to (1- len) :by len/3
:collect (format nil "~{~A ~}"
(subseq l i (+ i len/3))))))
list)))
CL-USER> (format-custom-list '((X X X) (X X X X X X) (X X X X X X X X X)
(X X X X X X X X X X X X)))
X X X
X X X X X X
X X X X X X X X X
X X X X X X X X X X X X
NIL
(Конечный nil
- это вывод format
, который не выводится в выходной поток t
. Если вы хотите получить строку из этой функции, используйте nil
как format
выходной поток.)