2009-08-12 54 views
5

我開始給我寫一些Common Lisp,並且只是將一些東西放在一起並對它們進行格式化。我該如何格式化一個共同的lisp alist?

讓我們假設我有一個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)))

回答

10

Freenode上的#CL-園丁通道建議做一個解構循環綁定是這樣的:

(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 2009-08-13 13:22:15

6

你是對的,因爲它看起來並不像有什麼辦法可以挑選除了格式的利弊細胞。

如果定義另一個函數來格式化單一關聯:

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

那麼它很簡單:

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

我不知道,如果這是一個進步與否。一方面,它更復雜一點,但另一方面,它確實將打印關聯分解爲(可重用的)函數,這可能很有用。

+6

你應該在格式中使用合格的函數名。 FORMAT解析* package *中的指定符號,並且在格式被調用時您永遠不會知道* package *是什麼。 – 2009-08-12 20:51:04

4

我認爲這裏的外賣的教訓實在是不使用點列表您alists。當然,你可以節省一個反應池,但是你放棄了所有漂亮的順序和列表功能。這是不值得的。您的格式例子是瑣碎完全形成列表:

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

轉換的ALIST細胞(a . 2)使用

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

,然後過程格式列出(a 2)

對於例如,要打印((a . 2) (b . 3))"a=2&b=3"

使用

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