2009-08-12 14 views
5

Sto iniziando a scrivermi un po 'di Common Lisp e sto solo imparando a mettere insieme le cose e a formattarle.Come posso formattare un alist in comune lisp?

Supponiamo ho un alist, in questo modo:

(defvar *map* '((0 . "zero") (1 . "one") (2 . "two"))) 

Come faccio a formattare in questo modo?

0: zero 
1: one 
2: two 

Stavo pensando qualcosa di simile (format t "~{~{~a: ~a~}~%~}" *map*), ma che dà un errore perché "zero" non è una lista e non si può prendere la macchina di esso.

Naturalmente, facendo (format t "~{~a~%~}" *map*) stampe

(0 . "zero") 
(1 . "one") 
(2 . "two") 

come si suppone, ma non è proprio quello che voglio. C'è un modo migliore per farlo rispetto al solo (dolist (entry *mapping*) (format t "~a: ~a~%" (car entry) (cdr entry)))?

risposta

10

Il canale # cl-giardinieri su Freenode suggerisce di fare un vicolo cieco ciclo destrutturazione in questo modo:

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

Non penso che ci sia un modo migliore per farlo; Avrei usato map():

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

mapcar è di più per il punto ... – skypher

6

Hai ragione, nel senso che non sembra che ci sia alcun modo per scegliere a parte una cella cons da FORMAT.

Se si definisce un'altra funzione per formattare un'unica associazione:

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

allora è facile:

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

io non sono sicuro se questo è un miglioramento o meno. Da un lato, è un po 'più complesso, ma d'altro canto, scinde l'add-on di stampa in una funzione (riutilizzabile), che potrebbe essere utile.

+6

Si dovrebbe usare nomi di funzioni qualificate in formato. FORMAT analizza il simbolo specificato in * pacchetto * e non si saprà mai quale sia il pacchetto * * al momento in cui viene chiamato il formato. –

4

penso che la lezione da asporto qui non è davvero utilizzare gli elenchi tratteggiate per i vostri alists. Si salva una cella di contro, certo, ma si rinuncia a tutte le funzioni di sequenza ed elenco. Non ne vale la pena. Il vostro esempio formattazione è banale con le liste completamente formati:

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

convertire il cellule ALIST (a . 2) elencare (a 2) utilizzando

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

e poi di processo in formato.

Per per esempio., Per stampare ((a . 2) (b . 3)) come "a=2&b=3"

uso

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