AutoLISP : le guide complet — Chapitre 8 / 16

Les listes

Le nom LISP signifie LISt Processing — traitement de listes. Les listes sont la structure de données fondamentale du langage. Tout en LISP est construit autour des listes : les données, les programmes, et même les définitions de fonctions. Comprendre les listes, c'est comprendre LISP.

Créer des listes

Avec la fonction list

La façon la plus courante de créer une liste :

(list 1 2 3)              ; → (1 2 3)
(list "a" "b" "c")        ; → ("a" "b" "c")
(list 10.0 20.0 0.0)      ; → (10.0 20.0 0.0) — un point 3D !

Les éléments d'une liste peuvent être de types différents :

(list "AutoCAD" 2025 3.14 T)  ; → ("AutoCAD" 2025 3.14 T)

Avec l'apostrophe ' (quote)

L'apostrophe est un raccourci pour créer des listes de valeurs littérales :

'(1 2 3)           ; → (1 2 3)
'("a" "b" "c")     ; → ("a" "b" "c")

Attention : l'apostrophe empêche l'évaluation. Avec list, les arguments sont évalués :

(setq x 5)
(list x 10)   ; → (5 10) — x est évalué à 5
'(x 10)       ; → (X 10) — x n'est PAS évalué, c'est le symbole X

Utilisez list quand vos éléments contiennent des variables ou des expressions, et ' quand vous avez des valeurs constantes.

Différence entre list et quote

Accéder aux éléments

car : le premier élément

(car '(1 2 3))      ; → 1
(car '("a" "b"))     ; → "a"

cdr : le reste de la liste (tout sauf le premier)

(cdr '(1 2 3))      ; → (2 3)
(cdr '("a" "b"))     ; → ("b")
(cdr '(1))           ; → nil (liste vide)

Pourquoi car et cdr ?

Ces noms viennent de l'architecture de l'ordinateur IBM 704 sur lequel LISP a été créé en 1958. car signifie Contents of the Address Register et cdr Contents of the Decrement Register. Ces noms sont restés par tradition, même si plus personne ne programme sur un IBM 704 !

IBM 704

Lawrence Livermore National Laboratory, Attribution, via Wikimedia Commons

nth : accéder par index

Pour accéder directement à un élément par sa position (commençant à 0) :

(nth 0 '(10 20 30))   ; → 10
(nth 1 '(10 20 30))   ; → 20
(nth 2 '(10 20 30))   ; → 30

last : le dernier élément

(last '(1 2 3))      ; → 3

length : nombre d'éléments

(length '(1 2 3))     ; → 3
(length '())           ; → 0
(length nil)           ; → 0

Combinaisons de car et cdr

AutoLISP propose des raccourcis pour les combinaisons fréquentes :

(cadr '(1 2 3))     ; → 2 — équivalent à (car (cdr '(1 2 3)))
(caddr '(1 2 3))    ; → 3 — équivalent à (car (cdr (cdr '(1 2 3))))
(cddr '(1 2 3))     ; → (3)

En CAO, ces combinaisons sont omniprésentes, car les points sont des listes de coordonnées :

(setq point '(10.0 20.0 5.0))

(car point)    ; → 10.0 (coordonnée X)
(cadr point)   ; → 20.0 (coordonnée Y)
(caddr point)  ; → 5.0  (coordonnée Z)

Mais personnellement, je préfère utiliser nth pour accéder aux coordonnées d'un point — c'est plus facilement compréhensible :

(nth 0 point)  ; → 10.0 (coordonnée X)
(nth 1 point)  ; → 20.0 (coordonnée Y)
(nth 2 point)  ; → 5.0  (coordonnée Z)

Construire et modifier des listes

cons : ajouter au début

cons ajoute un élément en tête d'une liste :

(cons 0 '(1 2 3))     ; → (0 1 2 3)
(cons "x" '("a" "b")) ; → ("x" "a" "b")

Techniquement, cons crée une paire pointée (dotted pair) — une cellule qui contient exactement deux valeurs. Si le second argument est une liste, le résultat est une liste normale (la paire pointe vers le reste de la chaîne). Sinon, le résultat est une paire pointée, signalée par un point entre les deux éléments :

(cons 1 2)             ; → (1 . 2) — paire pointée
(cons 1 '(2 3))        ; → (1 2 3) — liste

Le point . n'est pas un opérateur — c'est la façon dont AutoLISP affiche une paire dont le second élément n'est pas une liste. Vous pouvez aussi écrire une paire pointée littérale avec la syntaxe quotée :

'(8 . "MonCalque")     ; Paire pointée : clé 8, valeur "MonCalque"

Ne confondez pas une paire pointée avec une liste à deux éléments :

'(8 . "MonCalque")     ; → (8 . "MonCalque") — paire pointée (2 valeurs dans 1 cellule)
'(8 "MonCalque")       ; → (8 "MonCalque")   — liste de 2 éléments (2 cellules chaînées)

La différence est importante quand on utilise car et cdr :

;; Sur une paire pointée
(car '(8 . "MonCalque"))   ; → 8
(cdr '(8 . "MonCalque"))   ; → "MonCalque" (la valeur directement)

;; Sur une liste
(car '(8 "MonCalque"))     ; → 8
(cdr '(8 "MonCalque"))     ; → ("MonCalque") (une liste contenant la valeur)

Avec une paire pointée, cdr retourne directement la valeur. Avec une liste, cdr retourne une liste. C'est pour cette raison que les paires pointées sont préférées dans les listes d'association des entités AutoCAD : elles permettent d'extraire la valeur avec un simple cdr, sans devoir faire car en plus. Nous y reviendrons dans la section suivante.

append : concaténer des listes

(append '(1 2) '(3 4))       ; → (1 2 3 4)
(append '("a") '("b") '("c")) ; → ("a" "b" "c")

reverse : inverser une liste

(reverse '(1 2 3))   ; → (3 2 1)

Parcourir une liste

Avec foreach

foreach est la manière la plus simple de parcourir une liste :

(foreach element '("AutoCAD" "Inventor" "Revit")
  (princ (strcat "\nProduit : " element))
)

Résultat :

Produit : AutoCAD
Produit : Inventor
Produit : Revit

Résultat de foreach

Avec while et cdr

La technique classique pour parcourir une liste en LISP :

(setq maliste '(10 20 30 40 50))

(while maliste
  (princ (strcat "\nÉlément : " (itoa (car maliste))))
  (setq maliste (cdr maliste))
)

À chaque itération, car extrait le premier élément et cdr réduit la liste. Quand la liste est vide (nil), la boucle s'arrête.

Les listes d'association

Les listes d'association (association lists ou alists) sont un pattern très courant en AutoLISP. C'est l'équivalent LISP d'un Dictionary en C#/.NET ou d'un dict en Python : une structure qui associe des clés à des valeurs. Chaque élément est une paire pointée (clé . valeur) :

(setq personne
  (list
    (cons 0 "Jean")
    (cons 1 35)
    (cons 2 "Ingénieur")
  )
)
;; → ((0 . "Jean") (1 . 35) (2 . "Ingénieur"))

assoc : rechercher par clé

(assoc 0 personne)   ; → (0 . "Jean")
(assoc 1 personne)   ; → (1 . 35)
(assoc 9 personne)   ; → nil (clé introuvable)

Pour obtenir juste la valeur :

(cdr (assoc 0 personne))  ; → "Jean"

Les listes d'association dans AutoCAD

C'est exactement ce format que AutoLISP utilise pour représenter les entités AutoCAD. Chaque entité est une liste d'association où les codes DXF servent de clés :

;; Sélectionner la dernière entité dessinée et lire ses données
(setq donnees (entget (entlast)))

Le résultat ressemble à ceci :

((-1 . <Entity name: ...>)
 (0 . "LINE")
 (10 1.0 2.0 0.0)
 (11 5.0 8.0 0.0)
 ...)
  • Le code 0 contient le type d'entité ("LINE", "CIRCLE", etc.)
  • Le code 10 contient le point de départ
  • Le code 11 contient le point d'arrivée

Exemple pratique : analyser une sélection

(defun c:compter-types (/ selection index entite type-entite compteur)
  (setq selection (ssget))  ; Demander une sélection
  (if selection
    (progn
      (setq compteur '())
      (setq index 0)
      (repeat (sslength selection)
        (setq entite (ssname selection index))
        (setq type-entite (cdr (assoc 0 (entget entite))))

        ;; Chercher si ce type existe déjà dans le compteur
        (if (assoc type-entite compteur)
          (setq compteur
            (subst
              (cons type-entite (1+ (cdr (assoc type-entite compteur))))
              (assoc type-entite compteur)
              compteur
            )
          )
          (setq compteur (cons (cons type-entite 1) compteur))
        )
        (setq index (1+ index))
      )

      ;; Afficher les résultats
      (foreach paire compteur
        (princ (strcat "\n" (car paire) " : " (itoa (cdr paire))))
      )
    )
    (princ "\nAucune sélection.")
  )
  (princ)
)

Ce programme compte les entités par type dans une sélection. Ne vous inquiétez pas si certaines fonctions (ssget, sslength, ssname, entget, subst, 1+) sont nouvelles — l'objectif ici est de voir comment les listes d'association sont utilisées en contexte réel.

Résumé

Fonction Rôle Exemple
list Créer une liste (list 1 2 3)(1 2 3)
' Liste littérale '(1 2 3)(1 2 3)
car Premier élément (car '(1 2 3))1
cdr Reste de la liste (cdr '(1 2 3))(2 3)
nth Élément par index (nth 1 '(1 2 3))2
last Dernier élément (last '(1 2 3))3
length Nombre d'éléments (length '(1 2 3))3
cons Ajouter en tête (cons 0 '(1 2))(0 1 2)
append Concaténer (append '(1) '(2))(1 2)
reverse Inverser (reverse '(1 2 3))(3 2 1)
foreach Parcourir (foreach x lst ...)
assoc Chercher par clé (assoc 0 alist)

Dans le prochain chapitre, nous allons voir comment interagir avec l'utilisateur : lui demander de cliquer un point, de saisir un nombre ou un texte, grâce aux fonctions get* d'AutoLISP.


Coup de pouce Besoin d'un développement AutoCAD (AutoLISP, ObjectARX, .NET, VBA) ? Contactez-moi pour un devis gratuit.