Lisp at 3. Exemple 1 : Fonction générique, abstraction et réutilisation

Home
Up
Previous
Next

Chapitre 3.    Exemple 1 - Fonction générique, abstraction et réutilisation

Cet exemple montre l'économie d'écriture de code que représente l'utilisation de fonctions génériques. Il montre aussi que l'abstraction est une technique "naturelle" en Lisp (*).

La fonction SORT-ELEMENTS-BY-INDEX trie une séquence d'éléments optiques selon leur indice de réfraction, pour une longueur d'onde particulière.

(DEFUN SORT-ELEMENTS-BY-INDEX (ELEMENTS WAVELENGTH)
    (SORT
        ELEMENTS
        #'(LAMBDA (ELEMENT-1 ELEMENT-2)
             (< (ELEMENT-REFRACTIVE-INDEX ELEMENT-1 WAVELENGTH)
                (ELEMENT-REFRACTIVE-INDEX ELEMENT-2 WAVELENGTH)))))

Rappel : tous les mots appartenant à la définition du langage sont en italique.

Examinons la syntaxe du Lisp; elle est simple et uniforme : toute expression correcte du langage s'écrit sous la forme d'une parenthèse gauche, d'un opérateur (ou fonction), de 0 ou plusieurs arguments, et d'une parenthèse droite (un argument pouvant être lui-même une expression). Toute expression du langage (ou programme) est ainsi représentée sous la forme d'une liste, la liste étant une structure de données du Lisp (il y a uniformité de la représentation des programmes et des données).

DEFUN est l'opérateur de définition d'une fonction; la fonction SORT-ELEMENTS-BY-INDEX prend 2 arguments comme l'indique la liste d'arguments formels (ELEMENTS WAVELENGTH). Après la liste d'arguments de la fonction définie par DEFUN apparaît le corps de la fonction, soit ici, la liste commençant par SORT : (SORT ... ).

SORT est une fonction de tri générique qui fait partie du Common Lisp; elle a deux arguments, le premier étant une séquence d'objets à trier, le deuxième une fonction (prédicat) de comparaison de deux objets selon laquelle le tri devra être fait. Cet argument fonctionnel sera soit un nom de fonction, soit directement une définition de fonction, comme dans cet example.

SORT est dite fonction générique dans la mesure où elle accepte, comme argument, n'importe quel type de séquence (liste, vecteur ou chaîne de caractères). De plus, la taille de l'argument séquence est quelconque et la séquence peut contenir des objets de n'importe quel type. Enfin, il n'y a pas de contrainte sur la fonction de comparaison (elle doit simplement accepter deux arguments et renvoyer "vrai" ou "faux").

L'algorithme de tri utilisé par SORT dépend de l'implantation du Lisp utilisé : en général, cet algorithme est sophistiqué; il tient compte du type de séquence, de la longueur de la séquence et de la complexité de la fonction de comparaison.

Il est important de remarquer que la fonction utilisateur SORT-ELEMENTS-BY-INDEX est elle-même automatiquement générique.

Le premier argument de la fonction SORT est donc la séquence d'éléments optiques, ELEMENTS.

Le deuxième argument la fonction SORT est un argument fonctionnel: c'est une fonction de comparaison de deux éléments optiques, soit (LAMBDA ...); pour la signification de #', voir l'annexe 1. L'opérateur LAMBDA permet de définir des fonctions anonymes et peut être utilisé en place d'un argument fonctionnel, au lieu d'un nom de fonction. Contrairement à DEFUN, LAMBDA n'est donc pas suivi d'un nom de fonction : LAMBDA est directement suivi de la liste d'arguments formels, (ELEMENT-1 ELEMENT-2), et ensuite du corps de la fonction anonyme, (< (ELEMENT-REFRACTIVE-INDEX...)...).

La fonction de comparaison appelle la fonction ELEMENT-REFRACTIVE-INDEX qui calcule l'indice de réfraction d'un élément optique en fonction de la longueur d'onde (cette dernière fonction est définie par ailleurs). Cette dernière peut aussi être une fonction générique, valable pour différents types d'éléments optiques; elle doit renvoyer une valeur numérique acceptable pour le prédicat "plus petit", soit < (**)

Cet exemple démontre le haut pouvoir d'expression du Lisp; l'abstraction est maximum, l'essence conceptuelle de ce programme apparaissant clairement à tout lecteur attentif.

——————————

(*)    Le lecteur pourra préférer lire l'annexe 1 avant de lire cet exemple

(**)   A noter que le corps de l'argument fonctionnel (LAMBDA...) peut faire référence à la variable WAVELENGTH sans déclaration particulière, parceque cette référence est dans le champ textuel de cette variable (lexical scoping) ; c'est un des intérêts de la notion de fonction anonyme.

Home    Previous    Up    Next
contact
site map
Last update : 27/11/2001