Précédent Suivant
 
Deux constructeurs préexistent pour les listes:
  1. list
  2. cons
  3. et on peut leur ajouter une fonction intimement liée: append
Ces trois constructeurs ont des types bien différents: ils ne doivent pas être pris l'un pour l'autre. Le premier est une notation dont on pourrait se dispenser (quoique fastidieusement) à l'aide du second. Le troisième peut être défini à l'aide du second et avec le schéma récursif général des listes. En conclusion, seul le second est vraiment indispensable mais disposer des trois est un gage indéniable de confort et d'ouverture d'esprit: il en faut pour choisir le bon constructeur dans la bonne situation!
list Le constructeur list est une fonction n-aire qui construit d'un seul coup d'un seul une liste à l'aide de ses arguments. Les arguments de list sont, dans l'ordre, réunis en une liste. Ainsi:
 

(list 1 (+ 1 1) (/ 6 3))         ® (1 2 3)
(list (list (- 3 1)) (list 2))   ® ((2) (2))
(list)                           ® () 



Puisque les listes sont homogènes, le type du constructeur list est a×...®LISTE[a]. Dans ce type, les points de suspension indiquent la possibilité d'un nombre quelconque d'arguments mais tous de type a. La liste vide d'entiers est aussi la liste vide de listes d'images, la liste vide () ne dit pas quel est sa nature exacte. On dit que la liste vide est polymorphe.

cons Le constructeur cons construit les listes termes par termes. Il est très rudimentaire c'est pourquoi il est plus primitif que list. Sa particularité est de prendre une valeur d'un certain type t et une liste de type LISTE[t] et de créer une nouvelle liste de même type (à savoir LISTE[t]) dont le premier terme est le premier argument et dont les autres termes sont ceux de la liste de second argument. Le type de cons est donc t ×LISTE[t] ®LISTE[t].
 
La fonction cons a été nommée ainsi parce qu'elle cons-truit des listes.
 
On peut toujours se passer de list au profit de cons en explicitant comment la liste est construite pas à pas. Ainsi: l'expression (list (* 2 1) (+ 2 2)) peut elle aussi s'écrire (cons (* 2 1) (cons (+ 2 2) (list))). [On verra plus tard comment écrire autrement (list) sans faire intervenir list!] Ce que l'on vient de faire pour créer une liste de deux termes est encore lisible mais devient vite fastidieux pour une plus longue liste. Ainsi:  

(list 1 2 3 4 5 6 7 8 9) º (cons 1 
      (cons 2 
            (cons 3 
                  (cons 4 
                        (cons 5 
                              (cons 6 
                                    (cons 7 
                                          (cons 8 
                                                (cons 9 (list))))))))))



Heureusement que les éditeurs de textes illuminent les parenthèses associées sinon l'écriture serait un enfer (ce le fut avant l'invention des éditeurs WYSIWIG lorsque l'on comptait les parenthèses à la main!)

append Le dernier constructeur est la fonction bien utile append qui prend deux listes et renvoie une nouvelle liste dont les premiers termes sont ceux de son premier argument et dont les derniers termes sont ceux de son dernier argument. La fonction append prend donc deux listes de types compatibles, disons des LISTE[a] et renvoie une liste de même type LISTE[a]. Ainsi:
 

(append (list (* 1 1) (+ 1 1))
        (list 3) )              ® (1 2 3)
(append (list) (list 1 2))      ® (1 2)
(append (list 1 2) (list))      ® (1 2)
(append (list) (list))          ® () 



Choisir son constructeur Comment choisir son constructeur ? Cela dépend bien sûr de ce dont on dispose pour cela. Si l'on doit créer une liste dont on connaît les termes (dans l'ordre), utilisez list. Si l'on doit créer une liste terme par terme en les ajoutant par la gauche, cons s'impose. Enfin si l'on dispose déjà de listes toutes faites et que l'on cherche à les réunir, il est possible d'employer append.
 
La fonction append est assez coûteuse car, lorsque l'on regarde sa définition que voici:
 

;;; Id: c-qnc-append.scm,v 1.1 2001/10/01 07:44:18 queinnec Exp
 
(define (append l1 l2)
  (if (pair? l1)
      (cons (car l1) (append (cdr l1) l2))
      l2 ) )



On s'aperçoit qu'elle appelle autant de fois cons que la première liste a de termes. C'est donc toujours une très mauvaise idée d'utiliser append pour ajouter un terme en queue de liste, c'est d'ailleurs toujours une très mauvaise idée d'ajouter un terme en queue de liste quelque soit la méthode employée. Les listes sont disymétriques, on ajoute facilement en tête (avec cons), on verra également que l'on retire facilement des informations de la tête d'une liste et que donc l'accès aux listes par leur tête est toujours conseillé.
 
Le plus souvent une simple analyse des types des valeurs que l'on souhaite réunir en liste permet de savoir quel constructeur employer puisqu'ils ont tous des types distincts.
 
Petit conseil: n'écrivez jamais (append (list p) p') à la place de (cons p p'), ce serait commettre une énorme faute de mauvais goût que nous ne pardonnerions point!


 

Précédent Suivant