2009-08-12 13 views
5

私はコモン・リスプ(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)))よりこれを行う良い方法はありますか?

答えて

10

Freenodeのの#CL-庭師チャネルは、このような非構造ループバインドをやっ示唆:

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

私はそれを行うより良い方法はないと思います。私はmap()を使用します:FORMATからコンスセルを離れて選ぶためにどのような方法がありますようにそれが見えないことに

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

でmapcarはあなたが形式で修飾された関数名を使用する必要があります... – skypher

6

あなたは、正しいです。

あなたは、単一の関連付けをフォーマットする別の関数を定義する場合:

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

は、それは簡単です:

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

私は、これは改善であるかどうかはわかりません。一方ではもう少し複雑ですが、他方ではprint-assocを(再利用可能な)関数に分解してしまいます。

+6

ポイントによりです。 FORMATは* package *内の指定されたシンボルを解析し、フォーマットが呼び出された時点で*パッケージ*が何か分からないでしょう。 –

4

私はここでお持ち帰りのレッスンは、あなたの連想リストのための点線のリストを使用して、実際にはないと思います。 1つのコンスセルを保存しますが、すべての素敵なシーケンスとリスト関数をあきらめます。それだけの価値はない。あなたの書式設定の例では、完全に形成されたリストと簡単です:

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

は連想リスト細胞(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*))