Programming Paradigms
Ce document présente les principaux paradigmes de programmation ainsi qu'une introduction détaillée au langage LISP, un langage historique et fondamental en intelligence artificielle.
D'après le document Programming Paradigms
Cet article a été rédigé automatiquement à partir du document source, puis vérifié avant publication.
Document source
Programming, Computer Science · PDF · 46 pages · 1967
Afficher l'aperçu du document
Ce document présente les principaux paradigmes de programmation ainsi qu'une introduction détaillée au langage LISP, un langage historique et fondamental en intelligence artificielle. Il s'adresse aux étudiants en informatique souhaitant comprendre les différences entre paradigmes et maîtriser les concepts essentiels de LISP, notamment la manipulation des listes, la définition de fonctions et la récursion.
Les paradigmes de programmation
Le paradigme fonctionnel
La programmation fonctionnelle désigne une famille de langages qui accordent un rôle central aux fonctions. On peut raisonner en programmation fonctionnelle comme en mathématiques, notamment en utilisant des démonstrations par récurrence et des analyses récursives de complexité. Les fonctions récursives sont au cœur de ce paradigme.
Exemples de langages fonctionnels : Haskell, Standard ML, Ocaml.
Le paradigme procédural (ou impératif)
Le paradigme procédural est le plus ancien. Il met l'accent sur l'appel de procédures pour effectuer un calcul séquentiel. L'itération est le mécanisme central pour les calculs répétitifs, la récursivité y est rarement optimisée. La programmation impérative considère un programme comme une suite d'instructions pilotant un ordinateur.
Exemples historiques : Fortran (1967), Pascal (1970-1990). Aujourd'hui, C est le représentant majoritaire de ce paradigme.
Le paradigme à objets
Ce paradigme s'appuie sur la notion de classe et d'objet. Les objets possèdent des méthodes, qui sont des procédures destinées à être transmises sous forme de messages. Le calcul est décentralisé dans les objets, dont les méthodes peuvent être fonctionnelles ou impératives. Ce paradigme favorise la réutilisation et l'extensibilité du logiciel.
Exemples : Smalltalk (1970), popularisé avec Java et C++ dans les années 1990.
Introduction au langage LISP
Conçu en 1958 par J. McCarthy, LISP est l'un des plus anciens langages de programmation, longtemps utilisé en intelligence artificielle. Il se distingue par sa capacité à manipuler des symboles et par une syntaxe très simple basée uniquement sur la structure de listes.
Avantages de LISP
- Simplicité de la syntaxe, reposant uniquement sur les listes.
- Puissance du langage, notamment l'équivalence complète entre données et programmes.
- Interactivité grâce à un interpréteur principalement utilisé.
Les objets de base en LISP
L'atome
L'objet de base est l'atome, qui peut être :
- Un nombre (exemples : 126, -54)
- Un symbole, c'est-à-dire une séquence non vide de caractères (exemples : Le-Lisp, var, 1+x/y)
Les symboles servent à désigner les différents objets, qu'ils soient données ou fonctions.
La liste
La structure de base de LISP est la liste, une séquence ordonnée, éventuellement vide, d'atomes ou de listes, délimitée par des parenthèses.
Exemples :
- (* 3 7)
- (+ (* 3 7) (- 8 4) 10)
La liste vide, notée (), joue un rôle très important en LISP.
Expressions élémentaires et évaluation
Une expression élémentaire en LISP est une S-expression, qui est soit un atome, soit une liste.
Chaque S-expression a une valeur, notée VALEUR<s>. L'interpréteur LISP évalue une S-expression pour déterminer sa valeur.
Évaluation des atomes
- La valeur d'un nombre est lui-même.
- La valeur d'un symbole peut être :
- Prédéfinie et non modifiable (exemples : t et nil, où t vaut lui-même et nil vaut la liste vide ( )).
- Définie et modifiée dynamiquement, dans le cas d'une variable.
Évaluation des listes
Une liste (<s0> ... <sn>) est évaluée ainsi :
- <s0> est un symbole désignant une fonction, il n'est pas évalué.
- Les sous-expressions <s1> à <sn> sont évaluées pour obtenir VALEUR<s1> ... VALEUR<sn>.
- La fonction associée à <s0> est appliquée aux arguments VALEUR<s1> ... VALEUR<sn>.
- La valeur de la liste est le résultat de cette application.
Exemple d'erreur
Une parenthèse ouvrante doit toujours être suivie d'un nom de fonction :
(1 2 3 4)
Cette expression provoque une erreur car 1 n'est pas une fonction.
Éviter l'évaluation d'une S-expression
Pour désigner une S-expression sans l'évaluer, on utilise la fonction quote :
(quote (1 2 3 4)) = (1 2 3 4)
Abbréviation : '(1 2 3 4)
Définition de fonctions
Un programme LISP est une fonction ou un ensemble de fonctions, définies avec la primitive de.
Exemple :
(de **(z) (* z z))
Cette expression définit la fonction ** qui calcule le carré de z. La valeur retournée est le nom de la fonction définie.
Récursion
Une fonction est récursive si son nom figure dans sa propre définition.
Exemple 1 : Factorielle
(de fact(n)
(if (= n 1)
1
(* n (fact (- n 1)))))
Exemple 2 : Suite de Fibonacci
(de fib(n)
(cond ((= n 0) 0)
((= n 1) 1)
(t (+ (fib (- n 1)) (fib (- n 2))))))
Fonctionnement de l'interpréteur LISP
Le rôle de l'interpréteur est d'évaluer successivement des S-expressions selon le processus :
- Lire une S-expression
- Évaluer la S-expression
- Imprimer la valeur obtenue
Une session LISP consiste à faire évaluer plusieurs expressions respectant cette syntaxe simple.
Gestion des symboles fonctions et variables
LISP ne distingue pas lexicalement les symboles de fonctions et de variables, ce qui permet notamment de définir des fonctions récursives.
Deux classes de systèmes LISP existent :
- Systèmes bi-valents : chaque symbole peut avoir deux valeurs, une pour la variable (C-val) et une pour la fonction (F-val). Exemple : Le-Lisp, Mac-Lisp.
- Systèmes mono-valents : un symbole ne peut avoir qu'une seule valeur (C-val). L'évaluation d'une fonction donne directement sa définition.
Exemple d'affectation dans un système bi-valent
(setq a 3)
Cela met 3 dans la C-valeur de a. Les symboles comme +, -, * ont une F-valeur prédéfinie.
Types de fonctions en LISP
- SUBR : fonction prédéfinie en langage machine qui évalue ses arguments.
- EXPR ou LAMBDA : fonction écrite en LISP qui évalue ses arguments.
- FSUBR : fonction prédéfinie en langage machine qui n'évalue pas tous ses arguments (exemple :
setq).
On peut obtenir le type d'une fonction avec la primitive typefn :
?(typefn 'fact) = expr ?(typefn 'car) = subr ?(typefn '*) = nsubr
Constructeurs et sélecteurs de listes
cons
Ajoute un atome ou une liste en tête d'une liste.
?(cons 2 '(3 4)) = (2 3 4) ?(cons '(1 2) '(3 4)) = ((1 2) 3 4)
car
Retourne le premier élément (tête) d'une liste.
?(car '(1 2 3)) = 1 ?(car (cdr (cons 1 '(2 3)))) = 2
cdr
Retourne la liste sans son premier élément.
?(cdr '(1 2 3)) = (2 3)
Accès aux éléments suivants
cadr: second élémentcaddr: troisième élément
Exemple :
(cadr '(a b c)) = b (caddr '(a b c)) = c
Autres combinaisons
?(cdadr '(a (b c) d)) = (c d) ?(cddr '(a b c d)) = (c d) ?(cddar '((a b c d) (e) f)) = (c d) ?(cadar '((a b c) d e)) = b
append
Concatène plusieurs listes.
?(append '(ceci est) '(un support de cours) '(en Lisp)) = (ceci est un support de cours en Lisp)
list
Retourne une liste composée des éléments donnés.
?(list 1 2 '(3 4)) = (1 2 (3 4))
length
Retourne le nombre d'éléments de premier niveau d'une liste, ou 0 si l'argument est un atome.
?(length '(a (b c) d)) = 3
Prédicats
Les fonctions prédicats évaluent toujours leurs arguments et retournent nil si le prédicat est faux. Si vrai, la valeur peut varier selon le système, souvent t est utilisé pour vrai.
(atom <s>): retournetsiVALEUR<s>est un atome, sinon () si c'est une liste non vide.(null <s>): retournetsiVALEUR<s>est la liste vide (), sinon ()(eq <s1> <s2>): teste l'identité de deux atomes, retournetsi identiques, sinon ()(symbolp <s>): retournetsisest un symbole, sinonnil(constantp <s>): retournetsisest une constante (nombre, chaîne, ou nil), sinonnil(consp <s>): retournetsisest une liste non vide, sinonnil(listp <s>): retournetsisest une liste, sinonnil
Fonctions logiques
Les fonctions logiques retournent une valeur vraie ou fausse selon les valeurs logiques de leurs arguments. L'évaluation s'arrête dès qu'un résultat est déterminé pour éviter des calculs inutiles.
(or <s1> ... <sN>): retourne la valeur du premier argument différent denil, sinonnil. Évaluation arrêtée dès qu'un argument vrai est trouvé.(and <s1> ... <sN>): retourne la valeur du dernier argument si tous sont vrais, sinonnil.
Séquenceurs
(progn <s1> ... <sN>) évalue séquentiellement ses arguments et retourne la valeur du dernier.
Structures conditionnelles
IF
(IF <s1> <s2> <s3>) : si VALEUR<s1> est différente de nil, retourne VALEUR<s2>, sinon évalue et retourne VALEUR<s3>.
Exemples :
?(IF t 1 2) = 1 ?(IF nil 1 2) = 2 ?(IF nil 1) = nil
WHEN et UNLESS
(WHEN <test> <s1> ... <sN>): sitestest vrai, évalue toutes les expressionss1àsN.(UNLESS <test> <s1> ... <sN>): sitestest faux, évalue toutes les expressionss1àsN.
COND
La fonction conditionnelle la plus complète. Chaque clause est une liste (<ss> <s1> ... <sN>) où <ss> est une expression test. COND sélectionne la première clause dont VALEUR<ss> est différente de nil. Si le corps est vide, retourne VALEUR<ss>, sinon évalue les expressions du corps et retourne la valeur de la dernière.
Exemple de fonction utilisant COND
(de test (x y)
(COND
((> x y) 'sup)
((= x y) 'egal)
(t 'inf)))
?(test 12 5) = sup
?(test 5 8) = inf
Fonctions d'entrée/sortie
(print <expr>) évalue son argument, affiche la valeur obtenue et la retourne.
?(setq a 3) = 3 ?(print a) a = 3
Souvent utilisé avec des chaînes de caractères :
?(print 'salut) salut = salut ?(setq salut "Bonjour") = Bonjour ?(print salut) Bonjour = Bonjour
L'usage de print est justifié lorsque le résultat de l'évaluation n'est pas automatiquement affiché.
read
(read) est une fonction sans argument qui retourne la réponse de l'utilisateur sans l'évaluer. Le système invite l'utilisateur à saisir une expression.
?(setq x (read)) ? 5 ; réponse de l'utilisateur = 5
Glossaire des termes clés
- Atome : élément de base en LISP, soit un nombre, soit un symbole.
- Liste : séquence ordonnée d'atomes ou de listes, délimitée par des parenthèses.
- S-expression : expression élémentaire en LISP, soit un atome, soit une liste.
- VALEUR<s> : valeur d'une S-expression
saprès évaluation. - cons : fonction ajoutant un élément en tête d'une liste.
- car : fonction retournant le premier élément d'une liste.
- cdr : fonction retournant la liste sans son premier élément.
- Récursion : définition d'une fonction qui s'appelle elle-même.
- SUBR : fonction prédéfinie en langage machine évaluant ses arguments.
- FSUBR : fonction prédéfinie en langage machine n'évaluant pas tous ses arguments.
- EXPR/LAMBDA : fonction écrite en LISP évaluant ses arguments.
- Prédicat : fonction retournant
tounilselon une condition. - IF, COND, WHEN, UNLESS : structures conditionnelles en LISP.
- print : fonction d'affichage et de retour de valeur.
- read : fonction d'entrée interactive.
Points clés à retenir
- Les paradigmes fonctionnel, procédural et à objets proposent des approches différentes de la programmation.
- LISP est un langage symbolique basé sur les listes, avec une syntaxe simple et une évaluation basée sur les S-expressions.
- La distinction entre symboles de fonctions et variables est gérée différemment selon les systèmes LISP (bi-valents ou mono-valents).
- Les fonctions récursives sont fondamentales en LISP, permettant de définir des calculs complexes comme la factorielle ou la suite de Fibonacci.
- Les fonctions de manipulation de listes (cons, car, cdr, append, list) sont essentielles pour travailler efficacement en LISP.
- Les structures conditionnelles (IF, COND) et les fonctions logiques (and, or) permettent de contrôler le flux d'exécution.
- Les fonctions d'entrée/sortie (print, read) facilitent l'interactivité avec l'utilisateur.
Commentaires
Aucun commentaire pour le moment. Posez la première question.