Obligement - L'Amiga au maximum

Mardi 17 octobre 2017 - 06:03  

Translate

En De Nl Nl
Es Pt It Nl


Rubriques

 · Accueil
 · A Propos
 · Articles
 · Galeries
 · Glossaire
 · Hit Parade
 · Liens
 · Liste jeux Amiga
 · Quizz
 · Téléchargements
 · Trucs et astuces


Articles

 · Actualité (récente)
 · Actualité (archive)
 · Comparatifs
 · Dossiers
 · Entrevues
 · Matériel (tests)
 · Matériel (bidouilles)
 · Points de vue
 · En pratique
 · Programmation
 · Reportages
 · Tests de jeux
 · Tests de logiciels
 · Tests de compilations
 · Articles divers

 · Articles in english
 · Articles in other languages


Twitter

Suivez-nous sur Twitter




Liens

 · Sites de téléchargements
 · Associations
 · Pages Personnelles
 · Moteurs de recherche
 · Pages de liens
 · Constructeurs matériels
 · Matériel
 · Autres sites de matériel
 · Réparateurs
 · Revendeurs
 · Presse et médias
 · Programmation
 · Développeurs logiciels
 · Logiciels
 · Développeurs de jeux
 · Jeux
 · Autres sites de jeux
 · Scène démo
 · Divers
 · Informatique générale


Jeux Amiga

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Trucs et astuces

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Glossaire

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Partenaires

Annuaire Amiga

Amedia Computer

Relec

Hit Parade


Contact

David Brunet

Courriel

 


Programmation : Lisp - introduction
(Article écrit par Cédric Beust et extrait d'Amiga News - mars 1991)


Parlez-vous Lisp ? Probablement pas. La récente arrivée d'une nouvelle version d'AMXLisp va me servir de prétexte à une courte introduction à ce langage qui possède de nombreuses qualités. De plus, AMXLisp n'est pas la seule implémentation de Lisp disponible sur Amiga, alors, faites votre choix !

AMXLisp a été écrit par David Betz, auteur de la version bêta dont je parlerai à la fin de cette présentation, et l'interfaçage Amiga a été réalisé par François Rouaix (salut François !). Comme son nom l'indique, il s'agit de l'implémentation pour Amiga d'un dérivé de Lisp (XLisp) qui présente la particularité de posséder quelques aspects orientés objets. Je n'en ferai pas état dans cet article, mais nous en reparlerons très bientôt. Nous nous limiterons au sous-ensemble réellement Lisp d'AMXLisp mais sachez que celui-ci est conçu pour appeler des fonctions de bibliothèques de l'Amiga.

Premiers pas

Lisp est l'acronyme de "LISt Programming", et il raisonne donc essentiellement sous forme de listes. Une liste est composée d'éléments de base, appelés atomes. Les atomes sont des entiers, des caractères ou encore des chaînes. Une liste est encadrée par des parenthèses. Exemple de liste :

("ANews" 1 2 3)

On peut faire des opérations sur ces listes. Par exemple, en extraire le premier élément par la fonction "car" et la queue de la liste par "cdr".

> (car '("ANews" 1 2 3))
"ANews"

> (cdr '("ANews" 1 2 3))
(1 2 3)

Notez la façon qu'a Lisp d'écrire ses fonctions : (f a b c). Cela s'appelle la notation préfixée. D'autre part, la mystérieuse apostrophe qui précède la liste de test est directement liée à cette notation. En effet, Lisp essaie par défaut d'évaluer tout ce que vous lui donnez.

En l'occurrence, nous ne voulons pas que l'interprète évalue ("ANews" 1 2 3) comme étant l'appel de la fonction "ANews" avec les paramètres 1 2 3. Pour que Lisp n'évalue pas une liste, nous la faisons précéder par l'apostrophe.

Nous pouvons ensuite coller deux listes avec la fonction "cons", qui prend deux arguments et rend comme résultat la liste dont le "car" est le premier argument et le "cdr", le deuxième.

> (cons '(A B C) '(D E F))
((A B C) D E F)

Ce résultat vous surprend peut-être, pas vrai ? Relisez la définition de la fonction "cons". Si le résultat avait été (a b c d e f), le "car" de cette liste aurait été a, et non (a b c). Vous saisissez la nuance ? Il existe naturellement une fonction pour réellement concaténer deux listes "(append)".

Où l'on se mord la queue

Lisp se programme fondamentalement de manière récursive, et il constitue un excellent moyen de mieux comprendre cette méthode de programmation quelque peu surprenante au premier abord. Comment expliquer simplement la récursivité ? Pour paraphraser une phrase célèbre, "to understand recursion, you need to undersrand recursion" (pour comprendre la récursivité, il faut comprendre la récursivité). Ne rigolez pas, c'est exactement ça !

On résout un problème récursif en supposant que l'on sait le résoudre pour une complexité moindre. Prenons un exemple. Supposons que nous voulions obtenir l'inverse d'une liste. Soit '(A B C D E F), comment obtenir '(F E D C B A) ? Cette liste a une longueur de six. Supposons donc que nous sachions obtenir l'inverse d'une liste de cinq éléments. Comment pouvons-nous alors obtenir l'inverse d'une liste de six éléments ? C'est simple : c'est tout simplement cet inverse suivi du premier élément de la liste. Pour transcrire tout cela dans le monde lispien, l'inverse de '(A B C D E F) c'est la concaténation de l'inverse du cdr ('(F E D C B A)) et de son car (A), soit '(F E D C B A). Vous saisissez ?

Il faut bien entendu que la récursivité s'arrête quelque part. Ici, on partira de l'axiome que l'inverse d'une liste vide est elle-même. Voyons maintenant la fonction :

(defun inverse (1)
(if (null 1) 1
(append (inverse (cdr 1)) (list (car 1)))))

Vous voyez apparaître ici quelques nouvelles fonctions du langage. En premier lieu, la définition de fonction. Cela se fait par le mot-clé "defun" (dans cette catégorie de Lisp. Dans d'autres, cela peut être "de" ou "df"), suivi du nom de la fonction suivi de la liste des arguments suivi enfin du corps. Rappelez-vous que Lisp est un langage fonctionnel, et que tout s'exprime donc au moyen de résultats. Le corps doit donc retourner une valeur, qui sera la valeur de la fonction.

Ici, le corps est simple : il se compose du simple énoncé "if". Si la condition est vraie ("1 est vide"), on retourne "1", sinon on retourne la concaténation de l'inverse du "cdr" et du "car" (qu'il faut transformer en liste avant car "append" n'accepte de concaténer que des listes, et a priori, "(car 1)" peut être un symbole "(A)").

Maintenant, vérifions :

> (inverse '(A B C D E F))
(F E D C B A)

Et voilà. Commencez-vous à voir la puissance d'une telle technique ?

De plus (en plus (fort))

Nous allons passer à un autre exemple, maintenant : les tours de Hanoi. Un grand classique. Le problème est simple. Nous disposons de "n" disques de tailles décroissantes, empilés sur un piquet. Il y a trois piquets au total. Comment déplacer cette pyramide sur le piquet adjacent en ne déplaçant qu'un disque à la fois et en sachant qu'un disque doit toujours reposer sur un disque plus gros que lui ? On a bien entendu le droit de se servir du troisième piquet en tant qu'intermédiaire. Voyons comment résoudre ce problème avec trois disques :

LISP

Vous comprenez aisément que dès que le nombre de disques croît, le problème devient de plus en plus difficile à résoudre, et pourtant c'est toujours le même algorithme qui est utilisé. Celui-ci n'est pas itératif, vous vous en doutez !

Analysons donc ce problème d'un point de vue récursif. Nous voulons le résoudre avec "n" disques, supposons donc que nous savons le résoudre pour "n-1" disques. Cela suffit-il ? Eh bien oui :

LISP

L'hypothèse nous permet de ne plus être limité au déplacement d'un seul disque à la fois, mais par groupe de "n-1" disques. Comme d'habitude, il nous faut définir une solution quand "n=1" par exemple. Nous décidons alors qu'il suffit de déplacer ce disque du piquet "1" au piquet "2" et c'est fini. La récursivité se charge de résoudre le problème pour "n>1" !

Le listing peut donc se présenter comme cela :

LISP

Les quelques nouvelles instructions sont expliquées en commentaires. La fonction "(1- n)" est équivalente à "(- n 1)", mais attention ! Elle ne modifie pas la valeur de "n" : elle ne fait que retourner la valeur "n-1". Si vous regardez en parallèle le dessin expliquant la résolution par méthode récursive, vous verrez comme le programme est facile à suivre.

Voici son résultat pour "n=3" :

> (han 3)
1 vers 2
1 vers 3
2 vers 3
1 vers 2
3 vers 1
3 vers 2
1 vers 2

Synthèse

L'avantage principal de Lisp est avant tout d'être un langage interprété. Autrement dit, vous pouvez suivre son exécution pas à pas, examiner certaines variables et les modifier en cours. Bien sûr, cette facilité est obtenue aux dépens de la vitesse d'exécution, mais on demande rarement à un programme Lisp de s'exécuter rapidement. Si vous avez une idée et que vous voulez la mettre rapidement en application, Lisp est un très bon moyen de commencer : il ne vous impose pas de définir des structures de données qui n'en finissent pas, de déclarer vos variables, de passer par les étapes souvent longues de la compilation, etc. D'ailleurs, il est très fréquent de voir des maquettes de gros logiciels d'abord écrites en Lisp : cela permet d'avoir une idée très rapidement de ce à quoi le logiciel peut ressembler et de vérifier sa "faisabilité".

La notation préfixée peut sembler a priori rébarbative à assimiler. C'est une question d'habitude, et je la trouve personnellement beaucoup plus naturelle que la notation habituelle infixée et parenthésée (que ce soit la préfixée ou la postfixée, d'ailleurs, comme sur les calculatrices Hewlett-Packard). En effet, si je vous demande de calculer l'expression suivante :

i:=(k + 2)*(j + (n/2))

Commet allez-vous procéder ? Vous allez tout naturellement chercher l'expression la plus parenthésée, la calculer, remonter d'un niveau et recommencer. Ce qui est exactement équivalent à :

(setq i (* (+ k 2) (+ j (/n 2)))

Si j'ai passé volontairement tant de temps sur la récursivité, c'est qu'elle constitue le coeur de Lisp. Mais ce langage contient un nombre incalculable de fonctions qui permettent d'écrire des programmes bien plus gros que ceux que j'ai exposés ici. Il y a ainsi les énoncés habituels de boucles, de sélection, les tableaux et bien sûr toutes les fonctions imaginables sur les gestions de listes.

Rapide survol d'AMXLisp

L'interfaçage pour Amiga de cet XLisp a été écrit par François Rouaix, que certains de nos lecteurs connaissent déjà très probablement, mais l'auteur de la présente version est David Betz. En tant que version bêta, celle-ci souffre pour le moment de quelques bogues rendant la mise au point des programmes assez délicate, mais une vraie version ne tardera sûrement pas.

Les deux points forts d'AMXLisp par rapport à la plupart des autres Lisp sur Amiga sont qu'il dispose d'une mini-couche "orientée-objet" mais surtout qu'il est entièrement écrit pour utiliser les bibliothèques internes de l'Amiga. Ainsi, un programme d'exemple d'une soixantaine de lignes montre comment ouvrir une fenêtre et afficher un texte dedans.

Tous les fichiers "d'includes" sont présents et il semble donc en théorie possible de faire autant de choses en AMXLisp qu'en C, même s'il s'agit d'adressage de la mémoire.

Les programmes sont chargés à la main à l'aide de la commande "load" et il ne reste ensuite plus qu'à appeler le nom de la fonction principale. Si quelque chose cloche, il vous est possible de passer en mode trace et de suivre l'exécution pas à pas afin de localiser l'erreur. Il ne dispose pas d'éditeur mais la magie du multitâche fait que vous pouvez sans aucun problème lancer votre éditeur en tâche de fond et revenir y faire les modifications nécessaires en cas d'erreur.

La documentation est très complète mais elle présuppose une connaissance minimale en Lisp. Elle expose en détails la manière dont AMXLisp implémente la programmation par objets et liste de manière exhaustive toutes les fonctions qu'il connaît.

Les Lisp disponibles

Lisp vous intéresse ? Le choix sur Amiga ne manque pas. Outre la présente version d'AMXLisp, vous pourrez retrouver son ancienne version sur la disquette Fish n°181, qui est elle-même une amélioration de XLisp sur la Fish n°39. Mais je recommande fortement gnuemacs à ceux d'entre vous qui ont la possibilité de l'utiliser. En effet, indépendamment du fait qu'il dispose d'un mode Lisp permettant, entre autres, de vérifier les paires de parenthèses que vous écrivez (aide ô combien appréciable), je vous rappelle qu'il est écrit pour une bonne part en Lisp.

Enfin, gnumacs dispose d'un interprète Lisp complet permettant d'exécuter vos programmes avec les mêmes facilités qu'AMXLisp. Il possède en plus des fonctions propres vous permettant de le configurer selon vos besoins et d'écrire ou de modifier des modes. Bien entendu, il n'a aucun interfaçage Amiga, ni couche "objets", mais il reste un éditeur de choix pour la mise au point de programmes Lisp.


[Retour en haut] / [Retour aux articles]