cours/Remplissage du plan de L3.md
Oscar Plaisant c93facde92 update
2024-04-02 05:22:45 +02:00

46 KiB
Raw Blame History

up:: plan du mémoire de L3 #informatique #fac

Introduction

!mémoire de L3#^abstract

Définition et concepts importants

qu'est-ce qu'un paradigme

Un paradigme de programmation est une façon d'approcher la programmation et de formuler les problèmes et leurs formalisation dans un langage de programmation [@ParadigmeProgrammation2023]. En particulier, un paradigme fournit et détermine comment un développeur doit voir un programme. La notion de paradigme est notamment à dissocier de celles de méthode ou bien de design patterns, qui décrivent comment traîter des problèmes spécifiques et reconnus, et comment aboutir à une solution conceptuelle [@ParadigmeProgrammation2023]. Un paradigme est un concept plus "haut niveau", c'est-à-dire plus abstrait : chaque paradigme supporte un ensemble particulier de concepts (cohérents entre eux), qui peuvent être hérités d'une théorie mathématique, de principes fondamentaux, ou bien d'une vision sur ce que doit être la programmation 1.

Un paradigme de programmation est souvent principalement décrit par les concepts qu'il implémente ou non 2. C'est notamment cette approche qu'emploie la taxonomie des paradigmes de programmation (référence à une annexe) [@TaxonomiePrincipauxParadigmes].

Cependant, J.Huges, dans son article "Why Functional Programming Matters" [@hughesWhyFunctionalProgramming1989, p.1], fustige le fait que certains paradigmes (notamment la programmation fonctionnelle ref et la programmation structurée ref) sont trop souvent définis en termes des fonctionnalités qu'il n'implémentent pas, ou des contraintes qu'il posent 3. Cela est problématique car l'absence d'une fonctionnalité ne peut pas expliquer pourquoi un paradigme serait plus intéressant dans certains cas 4. L'auteur insiste donc sur le fait que les paradigmes devraient être définis en fonction des avantages structurels qu'il apportent pour résolution de certains types de problèmes.

C'est pour cette raison que, dans notre définition des différents paradigmes, nous chercherons à expliquer à la fois les principes fondamentaux de chaque paradigme, mais également à montrer brièvement pourquoi ceux-ci sont intéressants, c'est-à-dire répondre à la question "en quoi ce paradigme apporte-t-il quelque chose". Cela constituera une première partie de réponse à notre problématique.

Définition de concepts fondamentaux

état

L'état est la capacité, pour un programme, à retenir de l'information. "State is the ability to remember information, or more precisely, to store a sequence of values in time." (L'état est la capacité à retenir de l'information, ou, plus précisément, à stocker une séquence de valeurs dans le temps) [@royProgrammingParadigmsDummies, p.14].

Il est important de noter que la présence de variables n'implique pas toujours la présence d'état. En effet, une fonction peut avoir un paramètre sans avoir nécessairement d'état. Les variables des fonctions, si elles constituent une référence à une valeur, n'impliquent pas la présence d'état.

Note: la logique combinatoire fournit la preuve qu'il est possible d'établir un système de calcul sans aucune variable ni référence, ce qui rend l'absence d'état évidente [@LogiqueCombinatoire2023].

Fonction et procédure

Les termes "fonction" et "procédure" sont, selon les contextes et les auteurs, utilisés pour désigner différentes choses.

[!cite]+ Function (computer programming) - Page In computer programming, a function, subprogram, procedure, method, routine or subroutine is a callable unit[1] that has a well-defined behavior and can be invoked by other software units to exhibit that behavior. ^GNQR9GC2aRIAPAJ6Eg5383243

Par exemple, le livre "Structure and interpretation of computer programs" [@abelsonStructureInterpretationComputer1996] fournit la distinction suivante : les fonctions sont l'aspect mathématique du concept et sont définies en déclarant "ce qu'elle est" , en donnant des propiétés de cette fonction (une définition déclarative, voir Remplissage du plan de L3#programmation déclarative). Les procédures sont l'aspect programmatique du concept, et sont définies en déclarant "comment elle doit faire", en décrivant comment elle doit s'exécuter 5.

Cependant, certains auteurs utilisent le terme procedure même pour parler du concept théorique et mathématique (qui se rapproche du lambda-calcul) 6.

Nous utiliserons donc principalement le terme fonction, avec les définitions suivantes :

[!definition] fonction Une fonction est l'encapsulation d'un ensemble d'instructions. Une fonction peut posséder des paramètres qui peuvent influencer son exécution. Ces paramètres sont des valeurs ou des références qui sont données ("passées en argument") lors de l'appel de cette fonction. Une fonction peut retourner une valeur. Une fonction peut être appelée plusieurs fois et à plusieurs endroits, ce qui la rend réutilisable dans plusieurs contextes.

[!definition] fonction pure Une fonction pure est une fonction déterministe, c'est-à-dire que les mêmes arguments donnent toujours la même valeur de retour. Une fonction pure est une fonction sans effet de bord, c'est-à-dire qu'elle ne modifie pas l'état du système (en dehors de son champ local propre, dont la durée de vie est limitée).

Fermeture

Une fermeture (de l'anglais closure) est une fonction à laquelle on attache l'environnement local de l'endroit où elle à été définie 7 8. Cela permet à cette fonction d'accéder aux valeurs et aux références de cet environnement local, même si elle est appelée depuis un autre contexte (dans un autre champ local) 8. Du point de vue du développeur, cela signifie que l'exécution d'une fermeture soit le même que si les instructions étaient exécutées "à l'endroit" (dans le contexte où) la fermeture à été créée 9.

Un avantage considérable des fermetures est qu'elles permettent d'accéder aux valeurs et références d'un environnement local qui n'existe plus (car il à été libéré de la pile d'exécution) 10.

Description de quelques paradigmes

taxonomie des paradigmes de programmation

programmation impérative

La programmation impérative est un paradigme de programmation dans lequel le contrôle de flot d'exécution est explicite. Cela signifique que le programme spécifie pas à pas la marche à suivre pour obtenir le bon résultat. En programmation impérative, chaque étape modifie l'état global du système 11.

programmation déclarative

La programmation déclarative est un paradigme de programmation dans lequel la définition des programme se fait en déclarant la forme du résultat plutôt que la manière l'obtenir (comme on le fait en Remplissage du plan de L3#programmation impérative) Le développeur ne s'occupe donc pas de l'exécution, mais plutôt de comment spécifier le résultat. Le contrôle du flot d'exécution est implicite. En cela, la programmation déclarative s'oppose à la programmation impérative 12.

programmation fonctionnelle

La programmation fonctionnelle est un paradigme de programmation dans lequel les programmes sont exprimés comme des arbres d'expressions.

Le contrôle du flot d'exécution est donc fait en combinant des fonctions 13: la fonction principale prends en argument l'entrée du problème, puis elle est définit a partir d'autres fonctions, qui sont elles-même définies à partir de fonctions, et ce jusqu'à ce que les fonctions à la base de la définition (les feuilles de l'arbre d'expressions) soient des primitives du langages, ou bien des constantes 14. Cela distingue la programmation fonctionnelle d'autres paradigmes, notamment en programmation impérative, où l'état est beaucoup plus utilisé, notamment pour le contrôle du flot d'exécution.

Ces propriétés rapprochent beaucoup la programmation fonctionnelle des mathématiques 14.

[!cite]+ What Is Functional Programming? - Page Functional programming is about writing pure functions, about removing hidden inputs and outputs as far as we can, so that as much of our code as possible just describes a relationship between inputs and outputs. ^IU2KWY7La8P4TX53Jg5383243

Les fonction d'ordre supérieur sont centrales en programmation fonctionnelle. Les fonctions d'ordre supérieur sont des fonctions qui prennent en argument, ou renvoient d'autres fonctions. Ces fonctions d'ordre supérieur (aussi appelées "fonctionnelles") permettent donc de modifier ou combiner entre elles d'autres fonctions 15.

Pour que les fonctions d'ordre supérieur existent, il est nécessaire que les fonctions soient des citoyens de première classe, c'est-à-dire des entités traitées comme des valeurs du langage. Il est également nécessaire que le langage implémente les Remplissage du plan de L3#Fermeture, le cas échéant il serait impossible d'implémenter certaines fonctions d'ordre supérieur. La programmation fonctionnelle privée des fermetures (et donc des fonction d'ordre supérieur) s'appelle la programmation fonctionnelle de premier ordre (ref à la taxonomie en annexe)

Programmation fonctionnelle pure

La programmation fonctionnelle pure (parfois appelée simplement programmation fonctionnelle) est un paradigme dans lequel toutes les fonctions sont pures, c'est-à-dire qu'il n'existe pas d'état 16.

programmation structurée

La programmation structurée peut être définie, du point du vue théorique, comme un paradigme dans lequel le contrôle du flot se fait en utilisant des instructions de contrôle du flot d'exécution particulières (des structures de sélection et d'itération), et qui sont sous la forme de blocks 17. Les structures de sélection sont des structures particulières qui permettent de choisir quel groupe d'instruction sera exécuté en fonction de l'état du programme 18. Les structures d'itération sont des instructions qui exécutent répétitivement un block jusqu'à ce que le programme atteigne un certain état, ou bien que certaines opérations aient été appliquées sur chaque élément d'une collection 19.

Il est important de voir que le but de la programmation structurée est de produire des programmes plus clairs et de meilleure qualité, de par la modularité induite par la structuration du programme 20.

Une autre définition de la programmation structurée est une façon de concevoir les programmes

"In the first phase, that of top-down design, or stepwise refinement, the problem is decomposed into a very small number of simpler subproblems." [@floydParadigmsProgramming1979a, p.1]

"The second phase of the structured programming paradigm entails working upward from the concrete objects and functions of the underlying machine to the more abstract objects and functions used throughout the modules produced by the top-down design. [...] This approach is reffered to as the method of levels of abstraction, or of information hiding." [@floydParadigmsProgramming1979a, pp. 1-2]

"The absence of gotos and so on, has very little to do with this [the advantages strutcured programming, especially modularity]. It helps with 'programming in the small', whereas modular design helps with 'programming in the large'. Thus one can enjoy the benefits of structured programming in FORTRAN or assembly language, even if it is a little more work." [@hughesWhyFunctionalProgramming1989, p.2]

Programmation concurrente

La programmation concurente permet de gérer des programmes avec plusieurs ensembles d'instructions dont l'exécution doit être indépendante. En programmation impérative stricte, l'ordre des instructions définit leur ordre d'exécution, ce qui les rend interdépendantes. On dit alors que ces instructions sont séquentielles. La programmation concurrente indroduit le concept de concurrence, lorsque deux parties d'un programme n'ont pas de dépendance l'une avec l'autre 21.

"Le monde réel est concurrent : il consiste en des activités qui évoluent indépendamment" ("The real world is concurrent: it consists of activities that evolve independently." [@royProgrammingParadigmsDummies, p.25]).

les langages multi-paradigmes

Il existe beaucoup de langages qui implémentent plusieurs paradigmes de programmation [@ComparisonMultiparadigmProgramming2024]. Ces langages sotn appelés langages multi-paradigmes.

Par exemple, le langage prolog implémente à la fois la programmation logique et la programmation impérative 22. Un autre exemple peut être trouvé lorsque l'on ajoute une librairie de résolution de contraintes à un langage de programmation. Le paradigme de programmation par contraintes est alors ajouté au langage hôte, qui peut, par exemple, être un langage orienté objet 23.

Nous verrons l'avantage des langages de programmation multi-paradigmes dans la section Remplissage du plan de L3#diversité des approches

Définition de la puissance d'expression

La puissance d'expression (ou expressivité) d'un langage est la quantité et la diversité d'idées qu'il peut représenter ou communiquer 2425.

On distingue deux sens du terme. D'un côté, l'expressivité théorique, qui se concentre sur la possibilité théorique d'exprimer une idée dans un langage, indépendamment de la difficulté pour exprimer cette idée. De l'autre côté, l'expressivité pratique, qui se concentre sur la concision et la facilité d'expression de ces idées 26.

Expressivité au sens formel

La puissance d'expression au sens formel (ou expressivité formelle) est mesurée en regardant l'ensemble des idées qu'un langage peut exprimer. Ce concept d'expressivité formelle est surtout utile en mathématiques ou en informatique théorique (notamment dans la théorie des langages formels) 27

Pour un langage de programmation, il est presque indispensable d'être aussi expressif qu'une machine de Turing (Turing-complets) (ou un autre modèle de calcul équivalent), car cela est la condition nécessaire et suffisante pour qu'il puisse exprimer les problèmes calculables (par définition).

Il existe tout de même des langages qui n'ont pas la même expressivité formelle. On peut notamment citer les langages de description de données, dont le but est de représenter des données organisées (par exemple, les langages XML, JSON, YAML...), ou bien les langages de description d'ontologies, qui servent à représenter de façon informatique certains types d'ontologie. Notamment, OWL2 EL et OWL2 RL sont deux langages de description d'ontologies qui n'ont pas la même expressivité formelle : OWL2 EL n'implémente pas certains concepts qui peuvent pourtant être exprimés dans OWL2 RL 28.

Cependant, ces langages ne sont généralement pas qualifiés de "langages de programmation", puisqu'ils sont incapables d'exprimer un programme (c'est-à-dire des instructions exécutables), mais expriment seulement des données.

Il existe également des langages de programmation qui ne sont pas turing-complets (par exemple, le langage G-code, dans certaines implémentations 29), mais ces langages ne sont pas utilisés pour résoudre des problèmes de programmation : ils sont utilisés à des fins théoriques, ou pour des applications particulières (par exemple, le langage G-code est utilisé pour commander des machines à commande numérique 30).

Expressivité au sens pratique

L'expressivité pratique est la diversidé et la quantité d'idées qu'un langage de programmation peut exprimer facilement. Dans ce sens de l'expressivité, la facilité d'exprimer une idée est primordiale. Comme il est dit dans la section Remplissage du plan de L3#Expressivité au sens formel, la plupart des langages de programmation ont la même expressivité théorique. Cependant, il n'est pas suffisant pour l'expressivité pratique qu'une idée soit théoriquement exprimable : il est nécessaire qu'il soit aisé de le faire, que le langage implémente des fonctionnalités directement. Il est, par exemple, possible de faire de la programmation structurée (voir : Remplissage du plan de L3#programmation structurée) ou de la programmation fonctionnelle (voir : Remplissage du plan de L3#programmation fonctionnelle) dans un langage qui ne supporte pas nativement ces paradigmes (par exemple le langage assembleur). En général, pour tout concept x implémenté par un langage de programmation A, il sera toujours possible de créer un équivalent de x dans un langage B qui ne l'implémente pas nativement (à condition que B soit Turing Complet). Cependant, l'expressivité au sens pratique ne prends pas en compte cette possibilité, et ne considère que les idées directement (ou presque directement) implémentées et exprimables dans un langage.

L'expressivité pratique d'un langage est donc très liée aux paradigmes qu'il implémente. On pourrait même définir l'expressivité au sens pratique d'un langage comme la quantité de paradigmes qu'il implémente.

compromis entre expressivité et analysabilité

Plus un langage est expressif, plus il est complexe de l'analyser mathématiquement. Plus un langage est puissant expressivement au sens formel, plus il devient difficile (et impossible) de démontrer certains théorèmes sur ce formalisme 31. Cela est vrai également pour l'expressivité au sens pratique : "le fait d'éviter certaines techniques peut permettre de rendre plus aisée la démonstration de théorèmes sur la correction d'un programme -- ou simplement la compréhension de son fonctionnement -- sans limiter la généralité du langage de programmation." [@ParadigmeProgrammation2023].

Exemple de compromis : automates et grammaires

Les automates à pile et les machines de Turing forment un exemple de compromis entre analysabilité et expressivité formelle. Les automates à pile reconnaissent les langages non contextuels 32. Les machines de Turing reconnaissent les langages contextuels 33. Or, les langages non contextuels sont strictement inclus dans les langages récursivement énumérables 34 . On peut donc conclure que les machines de Turing ont un pouvoir d'expression formel supérieur à celui des automates à pile.

Cependant, si on pose le problème de l'appartenance d'un mot à un langage donné. Ce problème est décidable pour tous les langages non contextuels 35. Pourtant, ce problème est indécidable pour les machines de Turing 36.

On voit donc que les machines de Turing sont un formalisme plus expressif (certains concepts exprimés par des machines de Turing ne sont pas exprimables par des automates à pile) mais moins analysable (certains problèmes sont décidables sur les automates à pile, mais pas sur les machines de Turing).

Exemple de compromis : le non-déterminisme

Un langage de programmation est dit non déterministe lorsque son exécution ne dépend pas uniquement des spécifications du programme, c'est-à-dire que les spécifications laissent un choix lors de l'exécution du programme 37. Le non déterminisme est donc problématique, puisqu'il peut amener à créer des programmes dont le résultat est inattendu ou incertain. Ce pendant, certains paradigmes qui peuvent exprimer du non déterminisme restent utiles pour modéliser cetains problèmes 38.

C'est pourquoi certaines fonctionnalités, certains paradigmes, comme le non déterminisme et les paradigmes qui l'impliquent, devraient être utilisés uniquement si cela est nécessaire 39.

Paradigmes dans l'apprentissages

avantages de la diversité

  • pour apprendre, il est mieux d'apprendre plusieurs langages
    • car il en existe plusieurs
    • car le fait de connaître différentes approches de la programmation permet de mieux résoudre de nouveaux problèmes
      • on pourra choisir le paradigme adapté à notre problème (voir section résolution de problèmes)
      • on construit des modèles mentaux pour les problèmes

[!cite]+ Form and Content in Computer Science (1970 ACM turing lecture) - Page 9

  • To help people learn is to help them build, in their heads, various kinds of computational models.
  • This can best be done by a teacher who has, in his head, a reasonable model of what is in the pupil's head.
  • For the same reason the student, when debugging his own models and procedures, should have a model of what he is doing, and must know good debugging techniques, such as how to formulate simple but critical test cases.
  • It will help the student to know something about computational models and programming. The idea of debugging itself, for example, is a very powerful concept - in contrast to the helplessness promoted by our cultural heritage about gifts, talents, and aptitudes. The latter encourages "I'm not good at this" instead of "How can I make myself better at it?" ^CCMAKXHCaH39XI9D9g5383243p9

[!cite]+ 10 Things Software Developers Should Learn about Learning - Page 81 One key difference between beginners and experts is that experts have seen it all before. Research into chess experts has shown that their primary advantage is their ability to remember and recognize the state of the board.

[!note] Notes L'avantage des experts est d'avoir en mémoire beaucoup de cas, quand les débutants doivent réfléchir pour chaque nouveau cas. ^7WYHBT9DaSQN4T6Z8g5383243p4

[!cite]+ 10 Things Software Developers Should Learn about Learning - Page 81 Experts build up a mental library of patterns ^K2JKSWGEaSQN4T6Z8g5383243p4

[!cite]+ 10 Things Software Developers Should Learn about Learning - Page 81 seeing a variety of programming paradigms will help further. ^2PSW4XYMaSQN4T6Z8g5383243p4

problèmes de la diversité

[!cite]+ 10 Things Software Developers Should Learn about Learning - Page 84 Knowing multiple languages can be beneficial once they have been mastered, but sometimes transferring knowledge from one programming language to another can lead to faulty knowledge

[!note] Notes le transfert de connaissances d'un langage à un autre peut être avantageux, mais peut aussi créer de la connaissance fausse (si le transfert n'est pas pertinent à ce moment). ^588UCYYDaSQN4T6Z8g5383243p7

[!cite]+ The paradigms of programming - Page 3 If the advancement of the general art of programming requires the continuing invention and elaboration of paradigms, advancement of the art of the individual programmer requires that he expand his repertory of paradigms. ^R6BAAFNAaWWITR642g5383243p3

Paradigmes pour la résolution de problèmes

Les paradigmes fournissent un cadre pour la pensée

La définition même de paradigme explique déjà en partie l'existance des différents paradigmes : un paradigme donne une façon d'envisager la programmation. Comme il existe de nombreux types de problèmes, de nombreuses situations à modéliser, il semble normal que de nombreux paradigmes existent pour donner les concepts et outils nécessaires afin d'implémenter efficacement des solutions à ces problèmes.

L'existance de nombreux paradigmes de programmation peut donc être justifiée par diversité des problèmes rencontrés : chaque paradigme permet de répondre à une classe de problèmes précis. Par exemple, la programmation concurrente (voir : Remplissage du plan de L3#Programmation concurrente)permet de modéliser des situations où deux événements indépendants évoluent en même temps et indépendamment.

L'efficacité peut ici avoir deux sens : l'efficacité pour l'humain, c'est-à-dire l'aisance avec laquelle le développeur pourra implémenter une solution à son problème; et l'efficacité lors de l'exécution (efficacité pour la machine), qui dépend du temps et de l'espace mémoire nécessaires à l'exécution du programme. La nécessité de faire des compromis entre expressivité et analysabilité décris plus haut (voir Remplissage du plan de L3#compromis entre expressivité et analysabilité) peut avoir pour conséquence la nécessité de faire des compromis entre efficacité pour l'humain et efficacité pour la machine. En effet, une plus grande efficacité pour l'humain peut être atteinte par une plus grande expressivité (théorique, mais surtout pratique); or nous avons vu que cela pouvait mener à une moins grande analysabilité du langage, ce qui implique notamment que moins d'optimisation seront possibles lors de l'exécution d'un programme.

avantages des langages multi-paradigme

Lors de la résolution de problèmes, il peut être utile d'avoir de nombreux modèles à disposition, afin de pouvoir choisir celui qui correspond le mieux au problème actuel. Si ces modèles sont directement implémentés dans notre langage de programmation (si il supporte les bons paradigmes), la résolution de notre problème sera beaucoup plus aisée. "A language should ideally support many concepts in a well-factored way, so that the programmer can choose the right concepts whenever they are needed without being encumbered by the others." : Un langage devrait, dans l'idéal, intégrer de manière cohérente un grand nombre de paradigmes, pour permettre au développeur de choisir quels concepts ils souhaite utiliser, sans être encombré par les autres [@royProgrammingParadigmsDummies p.10].

Certains langages ne nécessitent pas un grand pouvoir d'expression, cars ils répondent à un besoin spécifique (voir Remplissage du plan de L3#Expressivité au sens formel). Cependant, la plupart des langages ont pour but de pouvoir résoudre une grande diversité de problèmes, et il est donc nécessaire qu'ils permettent de décrire et manipuler aisément un grand nombre de concepts.

créer un paradigme pour chaque type de problème

Le principe de l'extension créative (de l'anglais creative extension principle) est une méthode qui permet de créer de nouveaux paradigmes. Elle permet de trouver et d'organiser des conepts utiles à la programmation, pour réellement former un paradigme 40.

L'extension créative part de la constatation qu'un problème nécessite des modifications envahissantes (des modifications dans l'ensemble des contextes du programme) pour être résolu. Il est alors nécessaire de comprendre cette difficulté (pourquoi cette modification devient-t-elle envahissante ?), et de trouver un concept plus général, plus fondamental, qui résout cette difficulté, c'est-à-dire qui permet d'éliminer ces modification envahissantes pour retrouver un programme simple 41.

Par exemple, si il l'on cherche à modéliser plusieurs activités indépendantes dans un langage purement impératif, il faut implémenter soi-même plusieurs piles d'exécution, ainsi qu'un ordonnanceur... Les modifications impliquées par ce problème sont envahissantes. Cette complexité peut être évitée si notre langage implémente un concept (et donc un paradigme) : la concurence (voir Remplissage du plan de L3#Programmation concurrente) 42. La même logique peut s'appliquer à la gestion d'erreurs dans un programme. Si l'on veut être capable de gérer les erreurs dans un programme, il faut ajouter des condition dans le corps de chaque fonction, pour que chacune retourne le code d'erreur jusqu'à l'appel initial. Les modifications impliquées par ce problèmes sont envahissantes. Cette complexité peut être évitée si notre langage implémente un concept (et donc un paradigme) : les exceptions 43.

Floyd, dans son papier "The Paradigms of Programming", explique une méthode similaire qui lui permet de créer de nouveaux paradigmes : lorsqu'il résout un problème complexe, il essaie d'extraire l'essence de sa solution, de la simplifier pour obtenir une solution aussi directe que possible. Il cherche ensuite une règle générale qui lui permettrait de résoudre des problèmes similaires. Cette règle, si il la trouve, peut être le concept fondateur d'un nouveau paradigme 44.

On peut donc voir chaque paradigme comme la réponse à un problème particulier, à une situation qui serait complexe à modéliser sans ce paradigme.

Il serait même pertinent, de ce point de vue, d'encourager la création de nouveaux paradigmes dès que l'on trouve des problèmes nouveaux qui sont complexes à résoudre avec les paradigmes existant. On peut

Les paradigmes comme outil pour la pensée

Connaître un système de calcul ne permet pas d'immédiatement tout connaître sur son champ d'expressivité Notamment :

  • connaître un système de calcul ne permet pas (toujours) de connaître l'ensemble des problèmes décidables de ce système

De la même manière, connaître un langage de programmation ne permet pas de savoir immédiatement résoudre tous les problèmes que l'on peut rencontrer. Par exemple, la syntaxe des langages similaires à LISP est très simple et peut être apprise en quelques heures pour certains dialectes. Cependant, connaître la syntaxe complête et le fonctionnement de LISP ne permettra pas de résoudre tout problème : il est également nécessaire d'être capable de "faire le lien" entre un problème et un langage. C'est ce lien que les paradigmes de programmation permettent de faire, soit en donnant explicitement une méthode pour le faire (comme la paradigme programmation structurée), soit en définissant comment le programmeur doit voir les programmes, soit en implémentant certaines fonctionnalités utiles pour gérer certains problèmes.

!!!! contre la distinction entre les paradigmes !!!!

note: cette section pourrait être en ouverture

La dinstinction entre les différents paradigmes n'est pas toujours claire : beaucoup de langages sont Remplissage du plan de L3#les langages multi-paradigmes, et certains paradigmes peuvent être utilisés dans presque tous les langages (par exemple, la programmation structurée ref)

Certains auteurs considèrent que les paradigmes ne sont pas fondamentalement différents (voir : Remplissage du plan de L3#Au sens formel), mais plutôt que les paradigmes sont des courants de pensée, des traditions dans la programmation, rattachées à des communautés 45.

Greg Michaelson critique la distinction des paradigmes, en expliquant que, lorsqu'on les analyse profondément, les paradigmes sont en fait proche entre-eux 46.


  1. "A programming paradigm is an approach to programming a computer based on a mathematical theory or a coherent set of principles." [@royProgrammingParadigmsDummies] ↩︎

  2. "Each paradigm supports a set of concepts that makes it the best for a certain kind of problem. For example, object-oriented programming is best for problems with a large number of related data abstractions organized in a hierarchy. Logic programming is best for transforming or navigating complex symbolic structures according to logical rules. Discrete synchronous programming is best for reactive problems, i.e., problems that consist of reactions to sequences of external events." [@royProgrammingParadigmsDummies, p.10] ↩︎

  3. "It says a lot about what functional programming is not [...] but not much about what it is." [@hughesWhyFunctionalProgramming1989, p.1] ↩︎

  4. "It is a logical impossibility to make a language more powerful by ommitting features, no matter how bad they may be" [@hughesWhyFunctionalProgramming1989, p.1] ↩︎

  5. "The contrast between function and procedure is a reflection of the general distinction between describing properties of things and describing how to do things, or, as it is sometimes referred to, the distinction between declarative knowledge and imperative knowledge. In mathematics we are usually concerned with declarative (what is) descriptions, whereas in computer science we are usually concerned with imperative (how to) descriptions." [@abelsonStructureInterpretationComputer1996, p.28] ↩︎

  6. par exemple, Fellesein dans cette expression : "(let x be v in e) is expressible as (apply (procedure x e) v)" [@felleisenExpressivePowerProgramming1990, p.135] ↩︎

  7. "From an implementation viewpoint, a closure combines a procedure with its external references (the references it uses at its definition)." [@royProgrammingParadigmsDummies, p.24] ↩︎

  8. "Dans un langage de programmation, une fermeture ou clôture (en anglais : closure) est une fonction accompagnée de son environnement lexical. L'environnement lexical d'une fonction est l'ensemble des variables non locales qu'elle a capturées, soit par valeur (c'est-à-dire par copie des valeurs des variables), soit par référence (c'est-à-dire par copie des adresses mémoires des variables)[1]. Une fermeture est donc créée, entre autres, lorsqu'une fonction est définie dans le corps d'une autre fonction et utilise des paramètres ou des variables locales de cette dernière." [@FermetureInformatique2024] ↩︎

  9. From the programmers viewpoint, a closure is a “packet of work”: a program can transform any instructions into a closure at one point in the program, pass it to another point, and decide to execute it at that point. The result of its execution is the same as if the instructions were executed at the point the closure was created. [@royProgrammingParadigmsDummies, p.24] ↩︎

  10. "Une fermeture peut être passée en argument d'une fonction dans l'environnement où elle a été créée (passée vers le bas) ou renvoyée comme valeur de retour (passée vers le haut). Dans ce cas, le problème posé alors par la fermeture est qu'elle fait référence à des données qui auraient typiquement été allouées sur la pile d'exécution et libérées à la sortie de l'environnement. Hors optimisations par le compilateur, le problème est généralement résolu par une allocation sur le tas de l'environnement." [@FermetureInformatique2024] ↩︎

  11. "Control flow in imperative programming is explicit: commands show how the computation takes place, step by step. Each step affects the global state of the computation." [@toalProgrammingParadigms] ↩︎

  12. "Control flow in declarative programming is implicit: the programmer states only what the result should look like, not how to obtain it." [@toalProgrammingParadigms] ↩︎

  13. "In functional programming, control flow is expressed by combining function calls, rather than by assigning values to variables" [@toalProgrammingParadigms] ↩︎

  14. "Functional programming is so called because a program consists entirely of functions. The main program itself is written as a function which recieves the program's input as its argument and delivers the program's output as its result. Typically the main function is defined in terms of other functions, which in turn are defined in terms of still more functions, until at the bottom level the functions are language primitives. These functions are much like ordinary mathematical functions, and in this paper will be defined by ordinary equations." [@hughesWhyFunctionalProgramming1989, p.1] ↩︎

  15. "En mathématiques et en informatique, les fonctions d'ordre supérieur sont des fonctions qui ont au moins une des propriétés suivantes : elles prennent une ou plusieurs fonctions en entrée ; elles renvoient une fonction." [@FonctionOrdreSuperieur2023] ↩︎

  16. La logique combinatoire est un système de calcul dans lequel toutes les fonctions sont pures (il n'y a que des fonctions d'ordre supérieur dans ce système) [@LogiqueCombinatoire2023] ↩︎

  17. "Structured programming is a programming paradigm aimed at improving the clarity, quality, and development time of a computer program by making extensive use of the structured control flow constructs of selection (if/then/else) and repetition (while and for), block structures, and subroutines." [@StructuredProgrammingWikipedia] ↩︎

  18. "'Selection'; one or a number of statements is executed depending on the state of the program. This is usually expressed with keywords such as if..then..else..endif. The conditional statement should have at least one true condition and each condition should have one exit point at max." [@StructuredProgrammingWikipedia] ↩︎

  19. "'Iteration'; a statement or block is executed until the program reaches a certain state, or operations have been applied to every element of a collection. This is usually expressed with keywords such as while, repeat, for or do..until. Often it is recommended that each loop should only have one entry point (and in the original structural programming, also only one exit point, and a few languages enforce this)." [@StructuredProgrammingWikipedia] ↩︎

  20. "The most important difference between structured and unstructured programs is that the former are designed in a modular way. Modular design brings great productivity improvements. First of all, small modules can be coded quickly and easily. Secondly, general purpose modules can be reused, leading to faster development of subsequent programs. Thirdly, the modules of a program can be tested independently, helping to reduce the time spent debugging." [@hughesWhyFunctionalProgramming1989, p.2] ↩︎

  21. "For example, consider a program that consists of instructions executing one after the other. The instructions are not independent since they are ordered in time. To implement independence we need a new programming concept called concurrency. When two parts do not interact at all, we say they are concurrent.3 (When the order of execution of two parts is given, we say they are sequential.)" [@royProgrammingParadigmsDummies, p.25] ↩︎

  22. "Prolog: The first paradigm is a logic programming engine based on unification and depth-first search. The second paradigm is imperative: the assert and retract operations which allow a program to add and remove program clauses." [@royProgrammingParadigmsDummies, p.18] ↩︎

  23. "Solving libraries (e.g., Gecode): The first paradigm is a solver library based on advanced search algorithms, such as Gecode. The second paradigm is added by the host language, e.g., C++ and Java support object-oriented programming." [@royProgrammingParadigmsDummies, p.18] ↩︎

  24. "In computer science, the expressive power (also called expressiveness or expressivity) of a language is the breadth of ideas that can be represented and communicated in that language." [@ExpressivePowerComputer2023] ↩︎

  25. "The more expressive a language is, the greater the variety and quantity of ideas it can be used to represent" [@ExpressivePowerComputer2023] ↩︎

  26. "The term expressive power may be used with a range of meaning. It may mean a measure of the ideas expressible in that language: regardless of ease (theoretical expressivity); concisely and readily (practical expressivity)" [@ExpressivePowerComputer2023] ↩︎

  27. "The first sense dominates in areas of mathematics and logic that deal with the formal description of languages and their meaning, such as formal language theory, mathematical logic and process algebra" [@ExpressivePowerComputer2023] ↩︎

  28. "For example, the Web Ontology Language expression language profile (OWL2 EL) lacks ideas (such as negation) that can be expressed in OWL2 RL (rule language). OWL2 EL may therefore be said to have less expressive power than OWL2 RL. These restrictions allow for more efficient (polynomial time) reasoning in OWL2 EL than in OWL2 RL. So OWL2 EL trades some expressive power for more efficient reasoning (processing of the knowledge representation language)." [@ExpressivePowerComputer2023] ↩︎

  29. "G-code began as a limited language that lacked constructs such as loops, conditional operators, and programmer-declared variables with natural-word-including names (or the expressions in which to use them). It was unable to encode logic but was just a way to "connect the dots" where the programmer figured out many of the dots' locations longhand." [@Gcode2023] ↩︎

  30. "G-code (also RS-274) is the most widely used computer numerical control (CNC) and 3D printing programming language. It is used mainly in computer-aided manufacturing to control automated machine tools, as well as for 3D-printer slicer applications. The G stands for geometry. G-code has many variants." [@Gcode2023] ↩︎

  31. "The design of languages and formalisms involves a trade-off between expressive power and analyzability. The more a formalism can express, the harder it becomes to understand what instances of the formalism say. Decision problems become harder to answer or completely undecidable." [@ExpressivePowerComputer2023] ↩︎

  32. "[...] les langages algébriques, appelés aussi langages hors contexte, langages acontextuels, ou langages non contextuels. Ils sont reconnus par un automate à pile." [@HierarchieChomsky2023] ↩︎

  33. "Les langages [...] contextuels ou sensibles au contexte, sont exactement ceux reconnus par une machine de Turing non déterministe à mémoire linéairement bornée, appelés couramment automates linéairement bornés." [@HierarchieChomsky2023] ↩︎

  34. "La classe des langages contextuels (type 1) est incluse strictement dans la classe des langages récursivement énumérables (type 0). L'inclusion de la classe des langages algébriques (type 2) dans la classe des langages contextuels (type 1) doit être précisée car un langage contextuel ne contient jamais le mot vide ε. L'énoncé exact est : Un langage algébrique ne contenant pas le mot vide est un langage contextuel ou, de manière équivalente : Un langage algébrique est un langage contextuel éventuellement augmenté du mot vide." [@HierarchieChomsky2023] ↩︎

  35. "Le problème de l'appartenance d'un mot à un langage algébrique est décidable : il existe un algorithme qui, étant donnés la description d'une grammaire non contextuelle et un mot, répond en temps fini à la question de l'appartenance de ce mot au langage défini par cette grammaire (plus précisément, on peut le tester en un temps O(n^{3}) pour un mot de longueur n, grâce à l'algorithme CYK)." [@AutomatePile2021] ↩︎

  36. "Le problème de l'appartenance d'un mot à un langage de cette classe [la classe des langages récursivement énumérables] est indécidable." [@HierarchieChomsky2023] ↩︎

  37. "nondeterminism is when the execution of a program is not completely determined by its specification, i.e., at some point during the execution the specification allows the program to choose what to do next. During the execution, this choice is made by a part of the run-time system called the scheduler" [@royProgrammingParadigmsDummies, p.14] ↩︎

  38. "But paradigms that have the power to express observable nondeterminism can be used to model real-world situations and to program independent activities." [@royProgrammingParadigmsDummies, p.14] ↩︎

  39. "We conclude that observable nondeterminism should be supported only if its expressive power is needed." [@royProgrammingParadigmsDummies, p.14] ↩︎

  40. "Concepts are not combined arbitrarily to form paradigms. They can be organized according to the creative extension principle." [@royProgrammingParadigmsDummies, p.16] ↩︎

  41. "If the need for pervasive modifications manifests itself, we can take this as a sign that there is a new concept waiting to be discovered. By adding this concept to the language we no longer need these pervasive modifications and we recover the simplicity of the program" [@royProgrammingParadigmsDummies, p.17] ↩︎

  42. "If we need to model several independent activities, then we will have to implement several execution stacks, a scheduler, and a mechanism for preempting execution from one activity to another. All this complexity is unnecessary if we add one concept to the language: concurrency." [@royProgrammingParadigmsDummies, p.17] ↩︎

  43. "If we need to model error detection and correction, in which any function can detect an error at any time and transfer control to an error correction routine, then we need to add error codes to all function outputs and conditionals to test all function calls for returned error codes. All this complexity is unnecessary if we add one concept to the language: exceptions." [@royProgrammingParadigmsDummies, p.17] ↩︎

  44. "After solving a challenging problem, ! solve it again from scratch, retracing only the insight of the earlier solution. I repeat this until the solution is as clear and direct as I can hope for. Then I look for a general rule for attacking similar problems, that would have led me to approach the given problem in the most efficient way the first time. Often, such a rule is of permanent value." [@floydParadigmsProgramming1979a, p.3] ↩︎

  45. "In computer science, one sees several such communities, each speaking its own language and using its own paradigms. In fact, programming languages typically encourage use of some paradigms and discourage others." [@floydParadigmsProgramming1979a, p.2] ↩︎

  46. "Furthermore, it is not at all clear how programming paradigms are to be characterised and differentiated. Indeed, on closer inspection, apparently disparate programming paradigms are very strongly connected. Rather, they should be viewed as different traditions of a unitary Computer Science paradigm composed of programming languages which are all Turing Complete, complemented by methodologies which may all be subsumed by Computational Thinking." [@michaelsonProgrammingParadigmsTuring2020, p.41] ↩︎