我如何在常见的lisp中格式化alist?

时间:2009-08-12 01:10:29

标签: formatting lisp format common-lisp string-formatting

我开始给我写一些Common Lisp,我只是把事情放在一起并格式化。

假设我有一个alist,就像这样:

(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)))更好的方法呢?

5 个答案:

答案 0 :(得分:11)

Freenode上的#cl-gardeners频道建议像这样做一个解构循环绑定:

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

答案 1 :(得分:6)

你是对的,因为看起来没有办法从FORMAT中分离出一个利弊细胞。

如果您定义另一个函数来格式化单个关联:

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

然后很容易:

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

我不确定这是否有所改善。一方面,它有点复杂,但另一方面,它确实将print-assoc分解为(可重用)函数,这可能很有用。

答案 2 :(得分:4)

我认为这里的外卖课程实际上不是为你的列表使用虚线列表。当然,你可以保存一个cons单元格,但是你放弃了所有好的序列和列表函数。这不值得。您的格式化示例对于完全形成的列表来说是微不足道的:

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

答案 3 :(得分:1)

我认为没有比这更好的方法;我会用map()

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

答案 4 :(得分:1)

使用

将alist cell (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*))