5

我开始给我写一些Common 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)))

4

5 回答 5

11

Freenode 上的#cl-gardeners 频道​​建议像这样进行解构循环绑定:

(loop for (a . b) in *mapping*
  do (format t "~a: ~a" a b))
于 2009-08-12T03:21:32.177 回答
7

你是对的,因为看起来没有任何方法可以从 FORMAT 中挑选出一个 cons 单元格。

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

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

那么这很容易:

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

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

于 2009-08-12T01:53:54.703 回答
4

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

(defvar *map* '((0 "zero") (1 "one") (2 "two")))
(format t "~:{~a: ~a~}" *map*)
于 2009-08-12T18:40:00.697 回答
1

我认为没有更好的方法可以做到这一点。我会用map()

(format t "~{~a~%~}"
  (map 'list
    #'(lambda (entry)
      (format nil "~a: ~a" (car entry) (cdr entry))
    *map*))
于 2009-08-12T01:38:41.367 回答
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*))
于 2011-09-17T18:44:56.620 回答