Как использовать возможность итерации формата в списке conses - PullRequest
2 голосов
/ 12 апреля 2020

Я знаю, что могу использовать оператор format ~:{ ~} для прямой обработки списка списков, например,

CL-USER> (format t "~:{<~A,~A> ~}~%" '((1 2) (3 4)))
<1,2> <3,4>

Но теперь у меня есть список выражений, например, ((1 . 2) (3 . 4)) и выражение

(format t "~:{<~A,~A> ~}~%" '((1 . 2) (3 . 4)))

приводит к жалобе SBCL

The value
  2
is not of type
  LIST 

Есть ли format волхвы c, выполняющие трюк без необходимости использовать дополнительную итерацию с do или loop * * 1016

1 Ответ

3 голосов
/ 13 апреля 2020

Я вижу в основном 4 варианта

Не используйте формат для всего списка

Простое решение - избежать проблемы:

(loop 
  for (k . v) in '((1 . 2) (3 . 4))
  do (format t "<~a,~a> " k v))

Функция пользовательского формата

В качестве альтернативы используйте Tilde Sla sh для вызова функции, которая печатает cons-ячейки:

(defun cl-user::pp-cons (stream cons colonp atsignp)
  (declare (ignore colonp atsignp))
  (format stream "~a, ~a" (car cons) (cdr cons)))

(format nil "~/pp-cons/" (cons 1 2))
=> "1, 2"

Обратите внимание, что функция должна быть в пакете CL-USER, если Вы не указываете пакет. Если вы хотите настроить способ печати ячеек, вам нужно передать формат через специальную переменную:

(defvar *fmt* "(~s . ~s)")

(defun cl-user::pp-cons (stream cons colonp atsignp)
  (declare (ignore colonp atsignp))
  (format stream *fmt* (car cons) (cdr cons)))

А затем:

(let ((*fmt* "< ~a | ~a >"))
  (format t "~/pp-cons/" (cons 1 2)))

=> < 1 | 2 >

Конвертировать при печати

Создайте список fre sh, где неправильные списки заменяются правильными списками:

(format t
        "~:{<~a,~a> ~}~%"
        (series:collect 'list
          (series:mapping (((k v) (series:scan-alist '((1 . 2) (3 . 4)))))
            (list k v))))

Недостатком является то, что преобразование должно выделять память только для печати.

Изменить формат данных

Если правильные списки хороши для печати, возможно, они хороши и для других операций. Многие стандартные функции ожидают правильных списков. Обратите внимание, что список ((1 2) (3 4)) все еще является списком, значение просто заключено в cons-ячейку. Если вы решите использовать этот формат с самого начала, вам не придется конвертировать списки.

...