2009-08-12 9 views
5

Je commence à m'écrire du Common Lisp et je commence juste à comprendre les choses ensemble et à les mettre en forme.Comment est-ce que je pourrais formater un alist dans le lisp commun?

Supposons que j'ai un alist, comme ceci:

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

Comment formater je comme ça?

0: zero 
1: one 
2: two 

Je pensais quelque chose comme (format t "~{~{~a: ~a~}~%~}" *map*), mais qui donne une erreur, car ce n'est pas « zéro » une liste et vous ne pouvez pas prendre la voiture de celui-ci.

Bien sûr, faire (format t "~{~a~%~}" *map*) impressions

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

comme il est censé le faire, mais il est pas tout à fait ce que je veux. Y at-il une meilleure façon de faire cela que juste (dolist (entry *mapping*) (format t "~a: ~a~%" (car entry) (cdr entry)))?

Répondre

10

Le canal # cl-jardiniers sur Freenode suggère de faire une liaison en boucle déstructurant comme ceci:

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

Je ne pense pas qu'il existe une meilleure façon de le faire; J'utilisé map():

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

MAPCAR est plus au point ... – skypher

6

Vous avez raison, en ce qu'il ne semble pas comme il n'y a aucun moyen de prendre part une cellule de contre de FORMAT.

Si vous définissez une autre fonction pour formater une seule association:

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

il est facile:

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

Je ne suis pas sûr que ce soit une amélioration ou non. D'une part, c'est un peu plus complexe, mais d'un autre côté, ça fait ressortir print-assoc dans une fonction (réutilisable), ce qui pourrait être utile.

+6

Vous devez utiliser des noms de fonction qualifiés en format. FORMAT analyse le symbole spécifié dans * package * et vous ne saurez jamais quel est le * package * au moment où le format est appelé. –

4

Je pense que la leçon de plats à emporter ici est vraiment de ne pas utiliser des listes en pointillés pour vos alistes. Vous économisez une contre-cellule, bien sûr, mais vous abandonnez toutes les fonctions de séquence et de liste. Ce n'est tout simplement pas la peine. Votre exemple de mise en forme est trivial avec des listes entièrement formées:

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

Convertir les cellules ALIST (a . 2) à la liste (a 2) utilisant

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

et processus en format.

Pour exemple., Pour imprimer ((a . 2) (b . 3)) comme "a=2&b=3"

utilisation

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