Cours 7

Du code à l'outil

Deux bibliothèques LISP pour la science

Symbolic differentiation & numerical computing en pur LISP

Laurent Thiry — Programmation en C

« Un outil, c'est du code qui sert à écrire du code. »
— ou comment recycler son évaluateur en bibliothèque

1 / 16

Plan

  1. Outil ≠ Produit
  2. Homoiconicité
  3. Descendants du LISP
  4. Duo C + LISP
  5. Pourquoi ce cours existe
  6. Table de correspondance Cours 1–6
  7. Deux bibliothèques LISP concrètes
🧠 Spoiler : on va transformer ./let en vrai outil. Pas un PowerPoint. Pas une spec. Du code qui calcule.
2 / 16

Outil ≠ Produit

🔧 Outil

  • Résout un problème précis
  • Conçu pour vous
  • Minimal, hackable, réparable
  • Ex: grep, make, git
  • « On arrête quand ça marche »

📦 Produit

  • Résout un marché
  • Conçu pour des clients
  • Maximal, packagé, supporté
  • Ex: Mathematica, MATLAB, Excel
  • « On arrête quand c'est vendable »
💡 La thèse du cours : vous avez déjà écrit le socle (VM, parseur, évaluateur, REPL). Aujourd'hui, on construit des outils par-dessus, en LISP pur. Pas besoin de produit.
3 / 16

Homoiconicité

Définition : le code du programme est une structure de donnée du langage lui-même.

En C

// Le code est du texte, point.
// Analyser du C depuis du C ?
// -> parser + AST ~ 10k lignes

Le C peut manipuler du texte, mais
le texte n'est pas du C exécutable.

En LISP

;; Le code est une liste.
(define (square x) (* x x))

;; Je peux construire du code :
(list 'define (list 'square 'x)
      (list '* 'x 'x))

Code et donnée sont la même chose.
Une liste. Un arbre.

🔁 En C, écrire un programme qui manipule du C, c'est de la métaprogrammation. En LISP, c'est mardi. La frontière entre « code » et « donnée » n'existe pas.
4 / 16

Code = Arbre

;; Expression mathématique
(+ 1 (* 2 3))

;; Interprétée comme arbre :
    +
   / \
  1   *
     / \
    2   3
      

Un programme LISP est un arbre de syntaxe abstraite (AST) écrit en syntaxe concrète. Pas de parsing séparé : ce que vous tapez est l'arbre.

🤯 Conséquence : pour écrire un programme qui manipule des expressions mathématiques (dérivation, simplification), on écrit juste des fonctions sur des listes. C'est tout.
Mathematica, c'est 3M de lignes de C + un noyau LISP. Nous, c'est ./let + 50 lignes de bibliothèque. L'échelle diffère, pas le principe.
5 / 16

Descendants du LISP

Vous utilisez des langages LISP sans le savoir. Regardez l'arbre généalogique :

LISP
1958
Scheme
1975
Common Lisp
1984
Clojure
2007
AutoLISP
Dans AutoCAD depuis 1986.
15M d'utilisateurs.
Mathematica
Noyau LISP + notebooks.
5000 €/an. Même ID.
R / Julia
DSL scientifique.
Noyau C + bibliothèques.
🏗️ Le LISP, c'est le latin de l'informatique : personne ne le parle couramment en entreprise, mais tout le monde en descend. Les langages "modernes" réinventent juste les parenthèses avec une syntaxe différente.
6 / 16

Duo C + LISP

⚡ C — Le socle

  • Performance, mémoire, appels système
  • Évaluateur, parseur, primitives
  • ~1 000 lignes, compilé une fois
  • Stable, rapide, fiable

λ LISP — La couche créative

  • Manipulation d'arbres, récursion
  • Bibliothèques, DSL, prototypage
  • ~150 lignes, chargées à la demande
  • Flexible, expressif, extensible
🔧 C
performance
λ LISP
expressivité
📚 Bibliothèques
réutilisables
🚀 Vous
utilisateur
📌 Le pattern : le C fournit les briques, le LISP fournit le mortier. La même architecture que Mathematica (C + noyau LISP), R (C + packages), Julia (C + LLVM + Julia), Emacs (C + Elisp).
7 / 16

Pourquoi ce cours existe

🎯 Objectifs pédagogiques

  • Comprendre la différence entre produit et outil
  • Voir que LISP n'est pas un jouet — c'est l'architecture de logiciels réels
  • Prouver qu'on peut étendre son langage dans le langage lui-même
  • Réaliser que le C n'est pas une fin, mais un moyen

📖 Les vrais enjeux

  • Dans la vraie vie, on utilise des bibliothèques
  • On ne réécrit pas tout de zéro
  • Savoir faire un outil, c'est comprendre ceux qu'on utilise
  • Le C te donne le socle ; le LISP te donne le volant
🧑‍🏫 Si vous ne deviez retenir qu'une chose de ce cours : un programme, c'est d'abord un outil pour soi-même. Le produit, c'est ce qui arrive après des années de commercialisation. Vous êtes ici pour apprendre à forger, pas à vendre.
8 / 16

Correspondance Cours 1–6 → Outils

Chaque cours vous a donné une pièce du puzzle. Voici comment elles s'assemblent :

CoursConceptUtile pour
1Variables, boucles, fonctionsÉcrire les primitives C de l'évaluateur
2VM à pile, bytecodeComprendre l'exécution pas-à-pas
3Parseur, s-expressions, compilateurLire les fichiers .lisp
4Réseau, serveur HTTPℹ️ Contexte général
5Évaluateur, environnements chaînésExécuter let, lambda, define
6Persistance, prolog.lispCharger des bibliothèques .lisp
7Bibliothèques LISP🚀 mathematica.lisp + matlab.lisp
🎓 Leçon : chaque concept avait une raison d'être. On n'a pas appris le C pour faire du C. On a appris le C pour faire ce qu'on fait aujourd'hui.
9 / 16

Deux bibliothèques LISP

🧮 mathematica.lisp

Calcul formel — arbres d'expression, dérivation symbolique, simplification algébrique.

;; d/dx de 3x + 1
(deriv-simp '(Add (Mult (Val 3)
                       (Var x))
                  (Val 1))
            'x)
; → (Val 3)

50 lignes. Zéro dépendance.
Comme Mathematica, mais en moins cher.

📊 matlab.lisp

Calcul numérique — vecteurs, matrices, produit scalaire, norme, transposition.

;; Produit matriciel
(mulmat '((1 2) (3 4))
        '((5 6) (7 8)))
; → ((19 22) (43 50))

150 lignes. Tout en pur LISP.
Même pattern que NumPy (C + Python).

./let '(load mathematica.lisp)' '(…)' ou ./let '(load matlab.lisp)' '(…)'
10 / 16

🧮 mathematica.lisp — API

FonctionParamètresRetourneExemple
deriv expr var Dérivée brute (deriv '(Mult (Val 2) (Var x)) 'x)
(Add (Mult (Val 2) (Val 1)) (Mult (Val 0) (Var x)))
simplify expr Expression simplifiée (simplify '(Add (Val 0) (Var x)))
(Var x)
deriv-simp expr var Dérivée simplifiée (deriv-simp '(Mult (Var x) (Var x)) 'x)
(Add (Var x) (Var x))

Types de nœuds : Val (entier), Var (symbole), Add, Sub, Mult, Div.

🌳 Le calcul formel, c'est de la manipulation d'arbres. LISP est un arbre. C'est comme plier du papier quand le papier a déjà les plis marqués.
11 / 16

🧮 Dérivation en action

1

d/dx de 3x + 1

$ ./let '(load mathematica.lisp)'
         '(deriv-simp
            (quote (Add (Mult (Val 3)
                              (Var x))
                        (Val 1)))
            (quote x))'
; → (Val 3)
        

Attendu : 3. Obtenu : 3. ✓
La bibliothèque marche.

2

d/dx de x²

$ ./let '(load mathematica.lisp)'
         '(deriv-simp
            (quote (Mult (Var x)
                        (Var x)))
            (quote x))'
; → (Add (Var x) (Var x))
        

Résultat : x + x (non simplifié).
Le principe est là, la perfection viendra.

⏱️ Le prix du temps : Mathematica (10 ans, 5000 €/an) simplifie x + x en 2x. Notre version (1 après-midi, 0 €) laisse x + x. Même principe, échelle différente. Choisissez votre combat.
12 / 16

📊 matlab.lisp — Vecteurs

FonctionParamètresRetourneExemple
addveca ba + b(addvec '(1 2) '(3 4))(4 6)
subveca ba − b(subvec '(5 7) '(4 5))(1 2)
mulveca ba × b (elem)(mulvec '(2 3) '(5 6))(10 18)
scales vs × v(scale 5 '(1 2 3))(5 10 15)
dota ba · b(dot '(1 2) '(3 4))11
sumvΣ v(sum '(1 2 3))6
norm1v‖v‖₁(norm1 '(3 4))7
normv‖v‖₂(norm '(3 4))5.0
crossa ba × b (3D)(cross '(1 0 0) '(0 1 0))(0 0 1)

Chaque fonction : quelques lignes de LISP pur, zéro C.

13 / 16

📊 matlab.lisp — Matrices

FonctionParamètresRetourneExemple
addmata ba + b(addmat '((1 2)(3 4)) '((5 6)(7 8)))((6 8) (10 12))
submata ba − b(submat '((5 6)(7 8)) '((4 5)(6 7)))((1 1) (1 1))
transposemmᵀ(transpose '((1 2)(3 4)))((1 3) (2 4))
mulmata ba × b(mulmat '((1 2)(3 4)) '((1 0)(0 1)))((1 2) (3 4))
identitynIₙ(identity 3)((1 0 0) (0 1 0) (0 0 1))
zerosn m0n×m(zeros 2 3)((0 0 0) (0 0 0))
onesn m1n×m(ones 2 2)((1 1) (1 1))
🧩 Le pattern bootstrap : le C fournit le socle (parseur, évaluateur, primitives). Le LISP construit le reste (les bibliothèques). C'est exactement comme ça que fonctionnent R, Julia, et Mathematica — un noyau en C/C++, des bibliothèques dans le langage lui-même.
14 / 16

📊 Calcul matriciel en action

Addition de vecteurs

$ ./let '(load matlab.lisp)'
         '(addvec (quote (1 2 3))
                  (quote (4 5 6)))'
; → (5 7 9)
        

Produit matriciel

$ ./let '(load matlab.lisp)'
         '(mulmat (quote ((1 2)
                          (3 4)))
                  (quote ((5 6)
                          (7 8))))'
; → ((19 22) (43 50))
        

Matrice identité

$ ./let '(load matlab.lisp)'
         '(identity 3)'
; → ((1 0 0) (0 1 0) (0 0 1))
        

Norme euclidienne

$ ./let '(load matlab.lisp)'
         '(norm (quote (3 4)))'
; → 5.0
        
🐍 NumPy = 15 000 lignes de C + interface Python. matlab.lisp = 150 lignes de LISP + interface LISP. L'échelle change. Le principe est le même. (Et ça frime mieux en soirée.)
15 / 16

Trois couches, un outil

🔧 C
vm.c, let.c
λ Évaluateur LISP
REPL, primitives
📚 Bibliothèques
mathematica + matlab
🚀 Vous
utilisateur
Couche 1
C
Couche 2
Bibliothèques LISP
Couche 3
Vous

Pas de pip install. Pas de package manager.
Juste ./let '(load matlab.lisp)' et c'est parti.

Le génie, c'est 1% d'inspiration, 99% de transpiration.

Vous avez transpiré pendant 6 cours. Aujourd'hui, vous récoltez.

16 / 16