49 points par GN⁺ 2026-04-20 | 5 commentaires | Partager sur WhatsApp
  • Les différences entre syntaxes individuelles comptent moins que celles entre ensembles de motifs fondamentaux ; les langages de programmation se divisent en sept ur-langages selon leurs modes d’itération, de récursion et de composition
  • ALGOL, Lisp, ML, Self, Forth, APL et Prolog constituent la classification centrale, et chaque famille utilise un langage représentatif comme échantillon de référence pour situer les autres langages
  • Il est facile d’apprendre un nouveau langage qui partage un ur-langage déjà familier, mais passer vers un archétype inconnu demande de nouvelles voies de pensée et un temps d’apprentissage conséquent
  • ALGOL se caractérise par une organisation des fonctions centrée sur l’affectation, les conditionnelles et les boucles ; Lisp par les macros et le code sous forme de listes ; ML par les fonctions de première classe et la récursion ; Self par les objets à passage de messages ; Forth par une syntaxe fondée sur la pile ; APL par les tableaux n-dimensionnels ; et Prolog par une structure de faits et de recherche
  • Pour tous les programmeurs, la priorité est de bien maîtriser un langage de la famille ALGOL, puis d’apprendre SQL, avant de continuer ensuite à explorer régulièrement des ur-langages moins familiers, une approche plus avantageuse à long terme

Les sept ur-langages de la programmation

  • Lorsqu’on choisit un langage de programmation, il est plus important d’acquérir les motifs fondamentaux que de s’attarder sur les différences de syntaxe individuelles ; entre langages d’une même famille, les structures de base comme le parcours de tableaux ou l’itération combinatoire ont presque la même forme
  • Les différentes familles de langages diffèrent fortement par leurs modes d’itération, de récursion et d’organisation des programmes, et ces ensembles de motifs fondamentaux constituent des ur-langages distincts
  • Apprendre un nouveau langage qui partage un ur-langage déjà connu est une transition relativement facile, mais passer vers un ur-langage inconnu demande beaucoup de temps et de nouvelles voies de pensée
  • Dans l’ingénierie logicielle, on reconnaît sept ur-langages : ALGOL, Lisp, ML, Self, Forth, APL et Prolog
  • Chaque ur-langage est classé à partir d’un langage représentatif servant d’échantillon de référence, et les autres langages sont situés en comparant leur lignée à cet étalon
  • ALGOL

    • Un programme est organisé comme une suite d’affectations, de conditionnelles et de boucles, structurée en fonctions
    • De nombreux langages y ajoutent des systèmes de modules, des mécanismes de définition de nouveaux types de données, du polymorphisme, ou encore des structures de contrôle alternatives comme les exceptions ou les coroutines
    • La plupart des langages de programmation largement utilisés aujourd’hui appartiennent à la lignée de cet ur-langage
    • ALGOL lui-même comprend ALGOL 58, ALGOL 60, ALGOL W et ALGOL 68
    • Assembly language, Fortran, C, C++, Python, Java, C#, Ruby, Pascal, JavaScript et Ada se rattachent à cette lignée
    • C’est le plus ancien des ur-langages, avec une généalogie qui remonte jusqu’à la formalisation par Ada Lovelace de programmes pour la machine analytique de Babbage
    • Le langage machine et l’assembleur des ordinateurs de l’architecture Eckert-Mauchly, d’EDVAC aux premiers Univac, ainsi que les premières tentatives de langages de haut niveau, de l’A-0 de Grace Hopper à Fortran et COBOL, relèvent tous de cette forme
    • Dans les années 1960, le monde académique a fait progresser la programmation structurée pour rendre ces langages plus gérables ; le résultat en a été ALGOL 60, dont dérivent ensuite la plupart des membres de cette famille
    • Avec le temps, cette famille a eu tendance à absorber des fonctionnalités d’autres ur-langages
      • Dans les années 1980, des concepts de la famille Self ont été intégrés sous forme de classes, comme moyen de définir des types de données et d’implémenter le polymorphisme
      • Depuis 2010, des concepts de la famille ML ont également fait leur apparition
  • Lisp

    • Une syntaxe combinant expressions préfixées parenthésées et représentation en listes
      • (+ 2 3)
      • (defun square (x) (* x x))
      • (* (square 3) 3)
    • La représentation en listes, où des éléments séparés par des espaces sont entourés de parenthèses, est intégrée au langage, si bien que le code lui-même prend la forme d’une liste
    • Les macros peuvent recevoir une liste, la modifier, puis transmettre le code modifié au compilateur, ce qui donne aux programmeurs une structure permettant de redéfinir la sémantique du langage
    • Dans la plupart des usages, le code tend à fonctionner comme dans d’autres ur-langages, généralement ALGOL ou ML, mais le système de macros est l’élément distinctif
    • La syntaxe loop de Common Lisp n’est pas une fonctionnalité intégrée au langage, mais une forme définie par macro
    • Il y a eu beaucoup de variantes de Lisp au début, mais la communauté a fini par converger vers Common Lisp
    • Sussman et Steele ont exploré jusqu’où l’on pouvait aller avec les fonctions, et ont créé Scheme
    • On trouve aussi des Lisp spécialisés comme Lush pour le calcul numérique, AutoLISP comme langage de script d’AutoCAD, ou Emacs Lisp pour implémenter le comportement de l’éditeur Emacs
    • Plus récemment, Clojure s’est imposé comme une troisième grande branche de la famille Lisp
    • Apparue environ un an après Fortran, c’est la deuxième plus ancienne famille de langages encore utilisée aujourd’hui
    • Son point de départ était une question mathématique : comment noter une structure mathématique capable d’évaluer ses propres expressions
    • John McCarthy a proposé une réponse en 1958, qui a ensuite été implémentée sur ordinateur
    • Les premières versions de Lisp, à cause de leur arrière-plan mathématique, s’accordaient mal avec les machines de l’époque ; les questions de mémoire et de cycles CPU n’existaient pas en mathématiques, ce qui a rendu nécessaires des techniques comme le garbage collection
    • À la fin des années 1970 et au début des années 1980, il existait des machines conçues de fond en comble uniquement pour exécuter Lisp
    • Une grande partie des éléments des environnements de développement intégrés actuels y ont été inventés
    • À la même époque, Lisp était l’outil principal de la recherche en intelligence artificielle, et lorsque l’emballement pour l’IA des années 1980 n’a pas produit les résultats attendus, Lisp a chuté avec le domaine lors de l’AI Winter
    • Il a néanmoins survécu, et l’augmentation des performances des ordinateurs ainsi que l’adoption de ses fonctionnalités par d’autres langages ont réduit les difficultés d’implémentation
  • ML

    • Les fonctions y sont des valeurs de première classe, avec un système de types de la famille Hindley-Milner permettant d’exprimer des fonctions variées et des unions taguées
    • Toute itération y prend la forme de récursion
      • sum [] = 0
      • sum (x:xs) = x + sum xs
    • On utilise aussi des fonctions qui encapsulent des motifs d’itération et implémentent un comportement en recevant d’autres fonctions
      • map _ [] = []
      • map f (x:xs) = (f x) : (map f xs)
      Publicité
    • Certains langages, comme Miranda et Haskell, utilisent par défaut l’évaluation paresseuse
    • D’autres étendent le système de types dans plusieurs directions
      • OCaml tente une combinaison avec des concepts de l’ur-langage Self
      • Agda et Idris adoptent des systèmes de types dépendants mêlant valeurs et types
      • 1ML combine modules et types
    • ML a donné naissance à CaML, Standard ML et OCaml
    • Des familles apparentées comme Miranda, Haskell, Agda et Idris s’y rattachent également
    • ML était à l’origine le métalangage d’un programme de démonstration de théorèmes développé à Cambridge, au Royaume-Uni, et c’est de là que vient son nom
    • Il s’est ensuite diffusé comme langage autonome hors de ce contexte, gagnant en popularité en Europe, surtout au Royaume-Uni et en France
  • Self

    • Un programme est composé d’un ensemble d’objets qui s’échangent des messages, et tout le comportement est implémenté de cette manière
    • Les nouveaux objets sont créés en envoyant des messages à des objets existants
    • Même les conditionnelles fonctionnent via une variable qui référence soit l’objet true, soit l’objet false
      • Ces deux objets reçoivent un message prenant comme paramètres une fonction à exécuter si c’est vrai et une fonction à exécuter si c’est faux
      • L’objet true exécute la première fonction, l’objet false exécute la seconde
      • Le code appelant ne sait pas de quel objet il s’agit ; il se contente d’envoyer un message
    • Les boucles fonctionnent de la même manière, et en fabriquant les bons objets puis en les insérant au bon endroit, il est possible de redéfinir entièrement la sémantique du langage
    • Dans ces langages, le code source est généralement stocké non pas dans des fichiers texte mais dans un environnement live
    • Le programmeur modifie le système live et en enregistre l’état, au lieu de compiler des fichiers pour construire un système
    • Les exemples importants sont Smalltalk et Self
    • De nombreux langages n’empruntent qu’une partie du modèle d’échange de messages de cette famille, et cette adoption partielle est généralement ce qu’on appelle la programmation orientée objet
    • La plupart d’entre eux dérivent de Smalltalk, à l’exception de JavaScript, qui vient du système d’objets sans classes de Self
    • Le système objet de Common Lisp généralise ce modèle : au lieu qu’un seul objet reçoive un message, le runtime choisit le code à exécuter en fonction de tous les paramètres
    • Erlang, lui, déplace l’idée vers des threads d’exécution parallèles qui écoutent et envoient explicitement des messages, plutôt que de faire circuler le flux d’exécution d’objet en objet
    • Le langage d’origine est Smalltalk, développé à Xerox Parc à la fin des années 1970 et dans les années 1980
    • Dans les années 1980, il existait plusieurs systèmes Smalltalk commerciaux, et IBM a utilisé Smalltalk pour développer la collection d’outils de programmation VisualAge pour d’autres langages
    • Aujourd’hui, Smalltalk survit principalement sous la forme open source de Pharo Smalltalk
    • Beaucoup de recherches ont été menées pour exécuter Smalltalk rapidement et efficacement, avec comme point culminant le projet Strongtalk
    • Les découvertes de Strongtalk ont une importance historique, car elles ont servi de base au compilateur JIT HotSpot de Java
    • Smalltalk a repris des concepts de valeur et de type issus de langages antérieurs pour implémenter les classes ; chaque objet possédait une classe qui lui attribuait son type, et la classe créait les objets de ce type
    • Self a supprimé la notion de classe pour ne conserver que les objets
    • C’est pourquoi Self est choisi comme échantillon représentatif de cet ur-langage, en raison de sa forme plus pure
  • Forth

    • Les langages à pile sont en quelque sorte l’image miroir de Lisp, et partagent une syntaxe avec les calculatrices Hewlett Packard en notation polonaise inversée
    • Ils disposent d’une pile de données ; quand on écrit un littéral comme 42, il est empilé, et les noms de fonctions opèrent sur la pile sans paramètres explicites
    • Même l’arithmétique simple prend une forme inversée, comme 2 3 + 5 *
    • La définition de fonctions y est également très concise
      • Dans la plupart des variantes de Forth, : définit un nouveau mot
      • square signifie alors appeler dup puis *
      • dup duplique l’élément au sommet de la pile, * multiplie les deux éléments du sommet
    • Il est possible d’intercepter le parseur et de le remplacer par son propre code, ce qui permet de remplacer toute la syntaxe
    • Il est courant de voir des programmes Forth définir de petits langages, par exemple pour analyser directement un sous-ensemble de Fortran, une disposition de paquets, ou des diagrammes ASCII représentant les transitions d’une machine à états
    • On y trouve les différentes variantes de Forth, ainsi que PostScript, Factor et Joy
    • Joy est un langage purement fonctionnel qui utilise non pas une pile, mais une formalisation mathématique de la composition
    • Forth a été écrit pour la première fois en 1970 pour le contrôle de radiotélescopes
    • Il s’est ensuite largement diffusé dans l’univers des systèmes embarqués
    • Les systèmes Forth sont suffisamment faciles à amorcer qu’il existe des dizaines de variantes créées individuellement par des programmeurs pour leurs propres besoins
    • PostScript est apparu dans les années 1980 comme un moyen souple de décrire des documents sur les imprimantes
    • PostScript est à bien des égards plus contraint que Forth, mais définit dans le langage des opérations de base liées à la mise en page graphique
  • APL

    • Tout dans ce langage est un tableau n-dimensionnel
    • Les opérateurs sont composés d’un ou deux symboles et effectuent des opérations de haut niveau sur des tableaux entiers
    • L’expression y est extrêmement compacte, au point qu’une suite de symboles elle-même sert de marqueur d’opération sans avoir besoin d’autres noms
    • Par exemple, le calcul de la moyenne de la variable x s’écrit (+⌿÷≢) x
    • APL, J et K en sont les principaux exemples
    • Les opérations d’ordre supérieur sur les tableaux ont été en partie exportées vers de nombreux environnements comme MATLAB, NumPy et R
    • APL est né dans les années 1960 comme une notation mathématique créée par Kenneth Iverson, puis a été implémenté sur ordinateur
    • Il a depuis conservé un soutien de niche parmi les personnes qui effectuent des calculs lourds
    • Son langage descendant K a été particulièrement populaire dans les environnements financiers
    Publicité
  • Prolog

    • Un programme est constitué d’un ensemble de faits
      • father(bob, ed).
      • father(bob, jane).
    • Il utilise aussi des faits non ancrés qui permettent de déduire d’autres faits à l’aide de variables
      • grandfather(X, Y) :- father(X, Z), father(Z, Y).
    • Le runtime de Prolog prend ces faits et des requêtes, puis effectue une recherche pour trouver des résultats
    • Si l’on choisit correctement la structure des définitions de faits, on obtient la complétude de Turing
    • Dans Prolog, les termes qui composent les faits sont eux-mêmes un type de données distinct, que l’on peut construire puis transmettre au runtime
    • En cela, il occupe une place comparable aux macros de Lisp ou au remplacement du parseur en Forth
    • Un programme Prolog étant essentiellement une recherche, son optimisation se concentre sur l’ajustement de l’ordre de recherche et l’élimination précoce des chemins sans issue, comme dans les requêtes de base de données
    • Il comprend Prolog, Mercury et Kanren
    • Dans cette famille d’ur-langages, la majorité de la programmation réelle se fait directement en Prolog, et la communauté est très unifiée
    • Dans les années 1970, des logiciens français ont compris que l’on pouvait exprimer des programmes en logique du premier ordre, et ont commencé à essayer de les implémenter
    • Dans les années 1980, le projet japonais d’ordinateurs de cinquième génération a beaucoup misé sur Prolog, mais l’échec du projet a aussi terni sa réputation
    • Indépendamment de cela, les recherches se sont poursuivies pendant des décennies pour rendre le runtime Prolog efficace dans la plupart des cas et pour lui ajouter de nouvelles fonctionnalités
    • L’ajout de fonctions comme les contraintes numériques a conduit à la programmation logique par contraintes
    • Prolog continue d’apparaître dans des domaines de niche
      • La vérification de types de Java a été implémentée en Prolog pendant plusieurs années
      • Le premier outil de recherche dans le code source de Facebook reposait lui aussi sur Prolog

Comment l’utiliser

  • Pour la plupart des programmeurs, une partie ou l’ensemble de ces familles peut paraître très étrangère, mais chacune mérite qu’on y consacre du temps pour les voies de pensée et les nouvelles possibilités qu’elle ouvre
  • Il est très fréquent que deux choses paraissent totalement différentes depuis la perspective d’ALGOL, alors qu’elles ne sont qu’une comparaison triviale vues depuis une autre perspective
  • Priorités

    • Tous les programmeurs devraient bien connaître un langage de la famille ALGOL
    • Ensuite, il est recommandé d’apprendre SQL, un langage de la famille Prolog
      • C’est probablement ce qui apporte, dans une carrière, le plus grand bénéfice après ALGOL
    Publicité
  • Extension ensuite

    • Une fois ces deux familles maîtrisées, il est avantageux à long terme d’apprendre chaque année un nouveau langage appartenant à une famille d’ur-langages encore inconnue
    • Les langages proposés dans chaque famille, ainsi que leur ordre, sont les suivants
      • Lisp : PLT Racket
      • ML : Haskell
      • Self : Self
      • Prolog : Prolog
      • Forth : gForth
      • APL : K, via ok
  • Ajuster l’ordre

    • Si vous faites beaucoup de calcul numérique, il peut être pertinent d’apprendre K plus tôt
    • Si vous faites beaucoup de programmation embarquée, il peut être pertinent d’apprendre gForth plus tôt
    • Cela dit, l’ordre lui-même, ou même le choix exact du langage, n’a pas tant d’importance
    • On peut tout aussi bien apprendre Standard ML ou OCaml à la place de Haskell, Common Lisp à la place de PLT Racket, ou Factor à la place de gForth
  • Compléments inclus dans les notes

    • Même après avoir appris SQL, il reste nécessaire d’apprendre Prolog lui-même
      • Car son usage réel diffère considérablement de celui de SQL
    • Un avis de lecteur indique que, pour comprendre Forth en profondeur, une approche courante consiste à implémenter soi-même un interpréteur Forth
      • Forth est mentionné comme étant suffisamment petit pour qu’une seule personne puisse l’implémenter depuis zéro en relativement peu de temps
      • gForth est une bonne implémentation pour apprendre ANS Forth
      • Comme ressource d’apprentissage, le texte FORTH Fundamentals, Volume 1 de McCabe est mentionné
      • Parmi les autres Forth à examiner figurent PygmyForth, eForth et colorForth

5 commentaires

 
zkj9404 2026-04-21

C’est amusant.

 
tazuya 2026-04-20

À l’université, j’ai appris des matières de ma spécialité et fait des devoirs avec des langages de la famille ALGOL, Lisp et Prolog, ça me rappelle de bons souvenirs.

 
mhcoma 2026-04-20

Ces langages ont beaucoup apporté aux langages de programmation dominants d’aujourd’hui,
mais parmi eux, seul Forth semble avoir eu moins d’influence.

 
click 2026-04-21

Sans aller jusqu’à la notation préfixe, coder en notation postfixée reste vraiment trop peu pratique.

 
GN⁺ 2026-04-20
Avis Hacker News
  • Dans le cours de PL à Tufts, nous avons directement implémenté une mini-version de chacune des quatre premières familles de langages avant impératif, Lisp, ML, Smalltalk, et je suis ravi de voir que ce travail existe désormais aussi sous forme de manuel. C’est dommage que la partie Prolog, qui existait autrefois, ait disparu

    • Ce serait vraiment bien si une édition incluant la partie Prolog manquante se retrouvait quelque part, ne serait-ce que sur Internet Archive
  • S’il fallait corriger une seule chose dans la classification de cet article, je dirais que Ruby est clairement plus un langage orienté objet qu’un descendant d’Algol. L’influence de Smalltalk est forte, et on en voit encore des traces jusque dans les noms de la bibliothèque standard, avec par exemple collect plutôt que map. Dans Ruby, tout est objet du début à la fin, et il est plus naturel de comprendre un appel de méthode comme l’envoi d’un message à un objet. On le compare souvent à Python, mais leurs trajectoires d’évolution ont été assez différentes, même s’ils ont fini par converger vers des écosystèmes semblables. Pour moi, Ruby ressemble à un alpaga moelleux plus qu’à Python

    • Depuis les new style classes, Python peut lui aussi être vu comme un langage OOP pratiquement pur. Cela se remarque moins au niveau d’un Hello World, mais même les types primitifs sont tous devenus des objets. Pour les gens qui n’aiment pas l’OOP, montrer type(42) et dir(42) permet bien de souligner que même un entier est un objet
    • J’ai plutôt l’impression que désigner un langage prototype précis comme langage orienté objet ne fait qu’embrouiller les gens. L’OO ressemble davantage à un style de programmation, comme le procédural, et regrouper Python et C++ dans la même catégorie simplement parce qu’ils ont l’héritage multiple me paraît forcé
    • Cette métaphore du chameau me rappelle que camel, à l’origine, n’était-ce pas plutôt le symbole de Perl ?
  • J’aimerais ajouter une catégorie à cette généalogie des langages : les langages d’expression de preuves. Avec la correspondance de Curry-Howard, les programmes y sont aussi des preuves, et Lean en est un exemple représentatif. On peut les voir comme une sous-catégorie du fonctionnel, mais comme leur objectif principal est la vérification plus que l’exécution, je pense qu’ils méritent d’être traités sur un axe séparé

    • À mes yeux, les démonstrateurs de théorèmes et les types complexes ressemblent surtout à des extensions greffées sur des langages existants. Agda et Idris sont des langages fonctionnels enrichis de types complexes, tandis qu’Isabelle et Lean y ajoutent en plus la preuve interactive. Dafny ressemble davantage à un impératif enrichi de théorèmes et d’indices, et ACL2 se comprend facilement comme un Lisp avec theorem/hint. Et comme on le voit avec les traits de Rust, les typeclasses donnent parfois l’impression d’une forme de programmation logique fonctionnant au-dessus de langages fonctionnels ou impératifs
    • Par définition, cette famille n’a pas de complétude de Turing, donc j’ai du mal à les considérer comme de vrais langages de programmation. S’ils étaient Turing-complets, on pourrait produire de fausses preuves avec des programmes qui ne terminent jamais
    • Pour moi, ce courant dérive au fond directement de ML
    • Lean est clairement un langage de la famille ML à typage dépendant, proche d’Agda et d’Idris ; au sens large, on peut donc le ranger dans la catégorie ML. Et je ne crois pas non plus que l’objectif à long terme de Lean soit de reléguer l’exécution au second plan. Microsoft s’intéresse à l’écriture de vrais logiciels. À l’inverse, si l’on insiste davantage sur l’idée de « langage pour exprimer des preuves », il devient difficile d’exclure Prolog ; on pourrait alors voir Lean comme moitié ML, moitié Prolog. Dans cette perspective, la correspondance de Curry-Howard apparaît comme une manière parmi d’autres d’implémenter la logique du calcul
  • J’ai récemment replongé dans un projet de comparaison de langages : il s’agissait d’un benchmark qui décomposait en cycles, en parallèle, les 3 715 891 200 permutations signées de 10 caractères. Plus que des « langages prototypes », je voulais trouver, parmi les implémentations modernes de chaque paradigme, des langages qu’on pourrait réellement choisir pour de la programmation de recherche. Je ne regardais pas seulement les performances, mais aussi la facilité à travailler avec une aide IA et mon propre confort pour lire le code et raisonner dessus ; grâce à l’IA, j’ai aussi pu faire une sorte de tourisme en optimisant assez profondément chaque langage. Les résultats sont résumés ici, et voir F# en tête a été particulièrement surprenant

    • À première vue c’est inattendu, mais je pense que les détails font tout. Si l’on met Lean de côté, les écarts globaux ne sont pas si spectaculaires, et voir Chez seulement 2,5 fois plus lent que C++ reste une performance très honorable pour un langage JIT dynamiquement typé. Si F# est fort sur ce genre de tâche, c’est probablement parce que l’expérience de parallélisme sur .NET Core y est particulièrement mûre et sans surprise. Si ces chiffres correspondent au temps écoulé, une décomposition du temps CPU serait encore plus intéressante. En plus, les stratégies de parallélisation varient légèrement selon les langages, donc la comparaison ne se fait pas dans des conditions parfaitement identiques. Par exemple, une simple répartition sur threads en F# et les itérateurs parallèles de Rayon en Rust peuvent avoir des structures d’overhead différentes. Au final, Rust et C++ pourraient aller plus vite avec une gestion très fine des primitives de concurrence bas niveau de l’OS, mais ce serait encore un autre type de comparaison. On peut aussi se demander s’il faut autoriser l’usage de la C FFI en C ou en Haskell, et c’est pourquoi ce type de comparaison comporte inévitablement beaucoup de jugement qualitatif. À titre indicatif, le code Chez pourrait peut-être encore gagner en vitesse en stockant les permutations dans des fxvector et en utilisant des opérations spécialisées pour fixnum afin de réduire boxing/unboxing et allocations. La documentation liée est dans la documentation des objets de Chez Scheme
  • J’ai moi aussi écrit un article similaire ici. Je suis d’accord pour Algol, Lisp, Forth, APL et Prolog, mais pour le langage fonctionnel innovant j’ai choisi SASL, légèrement antérieur à ML, et pour la programmation orientée objet j’ai retenu Smalltalk, apparu avant Self. J’y ai aussi inclus Fortran, COBOL, SNOBOL et Prograph, que je considère chacun comme des langages ayant changé la donne à leur manière

    • Je préfère cette liste. Je suis surtout content d’y voir SNOBOL. Je ne l’ai jamais utilisé moi-même, mais c’est l’un des langages que j’ai découverts très jeune en tombant sur un livre à son sujet lors d’une vente de livres de bibliothèque publique, simplement parce que son nom m’avait amusé. Avant ça, je ne connaissais guère que BASIC, Logo, et un peu d’assembleur 6502 appelé depuis BASIC en suivant les exemples du manuel Atari BASIC. Et j’ai du mal à imaginer une liste de langages innovants qui laisserait de côté Fortran et COBOL, ou même leur ancêtre FLOW-MATIC. Le livre de référence était du côté du manuel Atari BASIC
    • Je comprends mal pourquoi Smalltalk plutôt que Self n’est pas dans la liste. Smalltalk est arrivé plus tôt, et Alan Kay est aussi la personne qui a inventé le terme même d’« OOP ». De la même façon, je tends aussi à voir ML comme un descendant de Lisp
  • J’aimerais aussi ajouter à cette discussion des familles sémantiques. Je pense à Verilog, aux Petri nets, aux Kahn process networks, aux dataflow machines, aux process calculi, aux systèmes réactifs, au term rewriting, aux familles constraint solver/theorem prover, ou encore à la programmation probabiliste. Je pense aussi à des langages comme Unison, Darklang, temporal dataflow ou DBSP, qui ne rentrent pas exactement dans les sept catégories existantes mais sont en pratique proches d’un usage de production. Cela peut sembler un peu tricher, mais la plupart reposent sur des modèles de calcul parallèles au modèle de machine de von Neumann. Depuis un moment, j’ai envie d’écrire un article du genre « Tous les modes de calcul que nous connaissons, au-delà de von Neumann »

    • Si un tel article sortait, je le lirais avec grand plaisir. En attendant, cela m’a rappelé une partie d’un texte de Steve Yegge. L’idée générale, c’est qu’une grande partie de l’enseignement moderne de l’informatique repose en fait sur le cadre conçu par von Neumann, et que le choix d’un dispositif séquentiel reflétait aussi les réalités de coût et de vitesse de fabrication de l’époque. Il insistait aussi sur le fait que beaucoup des éléments qu’on apprend — architecture machine, branchements, boucles, sous-routines, débogage, conversion entre systèmes de numération, modélisation des problèmes — se trouvaient déjà dans ses travaux. La citation concernée est archivée ici
    • En voyant la mention du term rewriting, je me suis souvenu d’un projet universitaire où je devais écrire le parseur de formules d’un tableur. J’ai été bloqué toute une semaine, puis j’ai fini par comprendre que si je réécrivais 1+1 sous une forme comme ADD(1,1), je pouvais le parser avec des techniques que je maîtrisais. En plus, comme je refusais bêtement d’apprendre les regex, le code a pris une forme assez étrange, et je me souviens encore d’un collègue disant : « Si Andy dit que ça marche, n’y touchons pas. » Quelqu’un d’une autre équipe a fait la même chose en regex avec un code environ 20 fois plus court que le mien
    • À propos des « langages émergents prêts pour le terrain », j’ajouterais que, selon moi, même si ce n’est pas encore totalement production-ready, des systèmes comme ChatGPT relèvent d’une catégorie voisine. Les considérer comme des langages de programmation est discutable, mais comme ils servent d’interface pour dire à un ordinateur quoi faire, cela me semble tout à fait défendable. Et le caractère non déterministe ne me paraît pas être une condition indispensable d’un langage de programmation
    • Je pense aussi que le texte de Sussman sur les propagators vaut le détour
    • Comme exemple de logic programming en S9 Scheme, cette ressource m’avait semblé bonne. Même sans acheter le livre, on peut récupérer directement le code, et après quelques bases via un manuel d’introduction comme Simply Scheme, la structure du solveur se lit assez facilement
  • Le cours « Concepts of programming languages » que j’ai suivi à TU Delft était mon préféré de tout le cursus d’info. On y a vu le C, le fonctionnel via Scala, et le prototypage via JavaScript, ce qui m’a beaucoup aidé quelques années plus tard pour apprendre Elixir. Il y avait aussi un cours où l’on programmait des agents Unreal Tournament en GOAL, un langage basé sur Prolog. Pendant longtemps, je n’ai pas su à quoi utiliser Prolog, puis j’ai fini par m’en servir pour fabriquer un correcteur orthographique qui forçait un LLM à corriger itérativement de mauvaises phrases générées en papiamento

    • J’ai suivi un cours similaire, et même si le professeur n’était pas extraordinaire, je suis très content de l’avoir pris. Le simple fait de connaître, même très superficiellement, d’autres langages prototypes élargit énormément la perspective, et l’effet est encore plus fort si l’on ajoute l’assembleur. On ne les utilisera peut-être jamais directement pour produire quelque chose, mais cela évite de tomber dans le piège du marteau qui fait voir des clous partout
    • J’étais aussi dans ce cours. La partie Unreal Tournament était l’un des cours les plus géniaux que j’aie jamais vus, et il me semble qu’elle a disparu l’année juste après la mienne. C’est dommage : j’ai l’impression que c’est devenu un cours d’IA banal comme on en voit partout. Je n’ai toujours pas trouvé énormément de bons cas d’usage pour Prolog, mais GOAL m’a laissé une impression bien plus forte. Et ce n’est que récemment que j’ai réalisé qu’on pouvait reproduire sa structure dans des langages plus « ordinaires », avec pas mal d’avantages à la clé, ce qui m’a laissé un peu amer
    • Je me demandais si le GOAL mentionné ici était Game Oriented Assembly Lisp
  • Je suis d’accord avec l’idée qu’il faut apprendre des langages de catégories différentes. Ce n’est qu’après avoir appris OCaml que les fonctions m’ont vraiment paru être des fonctions mathématiques, et Mathematica m’a donné l’habitude de considérer les expressions elles-mêmes comme des entrées. La notation polonaise inversée de PostScript m’a littéralement recâblé la façon de penser, bien au-delà de l’arithmétique simple. En revanche, je ne suis pas d’accord avec l’idée qu’on peut choisir indifféremment entre Java, C#, C++, Python ou Ruby. Si l’objectif est juste d’implémenter un tri rapide, cela peut se valoir, mais pour quelqu’un qui veut réellement construire quelque chose, le choix du langage peut faire une différence aussi grande que le jour et la nuit. Si on met Ruby dans les mains de quelqu’un qui veut créer un jeu 3D, ou Java dans celles de quelqu’un qui veut faire de la data science exploratoire ou du deep learning, on risque de lui couper toute motivation

    • Je ne gagnerai probablement jamais ma vie avec Rust, moi non plus, mais je ne regrette absolument pas de l’avoir appris. Rust m’a forcé à réfléchir très profondément à la propriété des données à l’intérieur d’un programme
  • Cet article m’a rappelé le livre de Bruce Tate, 7 languages in 7 weeks. C’est grâce à lui que j’ai découvert Erlang. En revanche, classer historiquement COBOL et Fortran dans la famille Algol me semble un peu forcé, même si cela rappelle aussi que l’histoire est, par nature, une forme de simplification réductrice

    • Je pense aussi qu’il est difficile de remonter encore plus loin pour établir une classification primitive. Les premiers langages d’assembly étaient déjà impératifs, mais ce qui rendait Algol, Fortran et Cobol intéressants, c’était leur capacité à permettre une programmation complexe grâce aux fonctions et à d’autres fonctionnalités de haut niveau. Algol a eu le plus de descendants, mais pour moi le premier vrai langage de programmation impératif était Fortran
    • À en croire Wikipédia, Fortran et Algol semblent tous deux avoir été développés autour de 1957, mais je me demandais lequel était réellement arrivé en premier et s’il y avait eu influence mutuelle ou recouvrement dans leur processus de conception
    • À vrai dire, COBOL est peut-être mieux vu comme un fossile vivant. Et le Fortran d’aujourd’hui me donne l’impression d’un langage fondé sur la lignée FORTRAN, mais ayant reçu horizontalement des traits de la famille Algol
  • Il y avait aussi une vieille discussion HN sur le sujet. Consulter cet ancien fil aide à remettre le contexte

    • Plus précisément, il s’agissait de la discussion du 4 mai 2023, avec 323 commentaires. Et parmi les plus anciennes, il y avait aussi ce fil du 30 septembre 2021, qui comptait 29 commentaires à l’époque