🧮 Arithmétique
(+ a b)
Addition de deux entiers.
(+ 2 3) → 5
(- a b)
Soustraction.
(- 10 3) → 7
(* a b)
Multiplication.
(* 6 7) → 42
(/ a b)
Division entière. Erreur si b = 0.
(/ 15 4) → 3
(> a b)
Comparaison : supérieur.
(> 5 3) → 1
(< a b)
Comparaison : inférieur.
(< 2 8) → 1
(>= a b)
Comparaison : supérieur ou égal.
(>= 4 4) → 1
(<= a b)
Comparaison : inférieur ou égal.
(<= 3 5) → 1
(= a b)
Égalité numérique.
(= 42 42) → 1
(sqrt x)
Racine carrée (flottant).
(sqrt 25) → 5
(sin x)
Sinus (radians, flottant).
(sin 0) → 0
(random)
Nombre flottant aléatoire dans [0, 1).
(random) → 0.374540
🔗 Logique
(and e1 e2 …)
ET logique (court-circuit, n'importe quel nombre d'arguments).
(and 1 0) → 0
(or e1 e2 …)
OU logique (court-circuit, n'importe quel nombre d'arguments).
(or 0 1) → 1
(not a)
Négation logique.
(not 0) → 1
(eq? a b)
Égalité entre entiers ou symboles.
(eq? 'a 'a) → 1
📦 Liaison & mutation
(let sym expr)
Crée une nouvelle portée avec la liaison sym = expr. Retourne la valeur.
(let x 42) → 42 puis x est lié
(set! sym expr)
Mute la liaison existante la plus proche. Si la valeur liée est une cellule, son contenu est modifié sur place. Erreur si sym n'existe pas.
(let x 10) (set! x 42) → x devient 42
🎮 Contrôle
(if cond then else)
Conditionnelle : si cond ≠ 0, évalue et retourne then, sinon else.
(if 1 2 3) → 2
(begin e1 e2 …)
Évalue les expressions en séquence. Retourne la dernière.
(begin (display 1) (display 2) 3) → 3
(quote expr)
Retourne expr sans l'évaluer. Sucre : 'expr.
'(a b c) → (a b c)
(null? x)
Teste si x est la liste vide.
(null? (list)) → 1
⚡ Fonctions
(lambda (params) corps)
Crée une closure anonyme. Retourne la fonction.
Paramètres : zéro ou plus, ex. (lambda (x y) …)
((lambda (x) (* x 2)) 21) → 42
(function nom (params) corps)
Crée une closure nommée et l'enregistre dans l'environnement. Supporte la récursion.
(function f (x) (* x 2)) (f 21) → 42
💡 lambda = fonction jetable. function = fonction réutilisable avec un rangement dans l'env.
Les deux créent une closure avec snapshot de l'environnement lexical.
🔩 Cellules mutables
(cell valeur)
Crée une cellule mutable contenant valeur. Allouée sur le tas avec compteur de références.
(cell 42) → #<cell:42>
(cell-ref cell)
Lit la valeur d'une cellule.
(cell-ref (cell 10)) → 10
🔗 Partager c'est aimer : quand on copie une cellule (sexp_copie), on incrémente le
compteur de références. Le Cell n'est libéré que quand plus personne ne le référence.
Deux closures peuvent ainsi partager la même cellule — la base des objets.
📋 Listes
(list e1 e2 …)
Construit une liste avec les éléments évalués.
(list 1 2 3) → (1 2 3)
(car lst)
Premier élément d'une liste. Erreur si liste vide.
(car (list 10 20)) → 10
(cdr lst)
Reste de la liste. () si liste à 1 élément.
(cdr (list 10 20 30)) → (20 30)
(cons a b)
Ajoute a en tête de la liste b.
(cons 1 (list 2 3)) → (1 2 3)
🎯 Pro tip : avec function, if, cons/car/cdr et la récursion,
vous pouvez implémenter map, filter, len, append… comme en vrai LISP.
🖨️ Entrée / sortie
(display expr)
Affiche la valeur sans saut de ligne. Retourne la valeur.
(display 42) → affiche 42 puis retourne 42
(print expr)
Affiche la valeur avec un saut de ligne. Retourne la valeur.
(print "hello") → affiche hello puis saute
💾 Persistance
(load "fichier")
Charge et exécute un fichier LISP. Chaque forme est lue et évaluée séquentiellement.
(load "prolog.lisp") → charge la bibliothèque standard
(save "fichier")
Sauvegarde l'environnement courant dans un fichier (format lisible, reproductible par load).
(save "monprog.lisp") → 1
🦄 Objets par passage de messages
Une closure + une cellule mutable = un objet. Le message est passé comme argument (un symbole).
Compteur — messages : 'inc, 'value, 'reset
(function make-compteur (init)
(let c (cell init))
(lambda (msg)
(if (eq? msg 'inc) (begin (set! c (+ (cell-ref c) 1)) (cell-ref c))
(if (eq? msg 'value) (cell-ref c)
(if (eq? msg 'reset) (begin (set! c 0) (cell-ref c)) 0)))))
(let c (make-compteur 100)) (c 'inc) → 101
Banque — messages : 'deposit, 'withdraw, 'balance
(function make-bank (initial)
(let solde (cell initial))
(let historique (list))
(lambda (msg mt)
(if (eq? msg 'deposit)
(begin (set! solde (+ (cell-ref solde) mt)) (cell-ref solde))
(if (eq? msg 'balance) (cell-ref solde)
0))))
🐍 Transpilation LISP → Python
transpile.c traduit le noyau fonctionnel vers Python 3. Les noms avec - ou ? sont convertis en _.
LISP → Python
Utilisation : ./transpile '(+ 1 2)' | python3
(let x 42) → x = 42
(+ x 1) → x + 1
(lambda (x) (+ x 1)) → lambda x: x + 1
(function f (x) (* x 2)) → def f(x): return x * 2
(if c t e) → t if c else e
(quote (a b)) → ['a', 'b']
(list 1 2 3) → [1, 2, 3]
(car lst) → lst[0]
(cdr lst) → lst[1:]
(cons a b) → [a] + b
(display x) → print(x, end='')
(print x) → print(x)
(begin a b c) → a ; b ; return c (dans def)
Exemple complet
Factorielle en LISP transpilée et exécutée :
$ ./transpile '
(function fact (n)
(if (eq? n 1) 1
(* n (fact (- n 1)))))'
'(print (fact 5))' | python3
120
Avec map et filter :
$ ./transpile '(function map ...)' '(function even ...)'
'(print (map even (list 1 2 3 4 5)))' | python3
[False, True, False, True, False]
🚀 Utilisation
Ligne de commande
# Plusieurs expressions
./let '(let x 10)' '(+ x 2)' '(print x)'
# REPL interactif
./let
Transpiler
# Générer du Python
./transpile '(let x 42)' '(+ x 1)'
# Générer et exécuter
./transpile '(...)' '(...)' | python3
# Sauvegarder le Python
./transpile '(...)' > script.py
python3 script.py
⚙️ Fonctions natives (C → LISP)
Ces fonctions sont écrites en C et enregistrées dans l'environnement global
au démarrage de let. Elles s'utilisent comme des fonctions LISP normales.
(random)
Nombre flottant pseudo-aléatoire dans [0, 1).
(random) → 0.374540
(sqrt x)
Racine carrée. Accepte entier ou flottant.
(sqrt 25) → 5
(sin x)
Sinus trigonométrique (radians).
(sin 0) → 0
🧩 Principe : une native est une fonction C de type
NativeFn. Le dispatch se fait par is_native() dans
evaluer_env. Le LISP ne fait pas la différence entre une closure
et une native — c'est la même syntaxe d'appel.
📚 Bibliothèque standard — prolog.lisp
Chargé automatiquement au démarrage de let (silencieux si absent).
21 fonctions écrites en LISP pur qui étendent le langage.
(fact n)
Factorielle de n (flottant).
(fact 5) → 120
(puissance x n)
xn (exponentiation entière).
(puissance 2 10) → 1024
(cos-iter x k n sign)
Itération interne pour le calcul de cos par série de Taylor.
(cos x)
Cosinus (10 termes de la série de Taylor).
(cos 0) → 1
(range start step stop)
Liste de start à stop avec le pas step.
(range 0 2 8) → (0 2 4 6 8)
(iota n)
Liste des entiers de 0 à n−1.
(iota 5) → (0 1 2 3 4)
(repeat x n)
Liste de n copies de x.
(repeat 42 3) → (42 42 42)
(length xs)
Longueur d'une liste.
(length (iota 10)) → 10
(take n xs)
Les n premiers éléments.
(take 3 (iota 10)) → (0 1 2)
(drop n xs)
Enlève les n premiers éléments.
(drop 7 (iota 10)) → (7 8 9)
(append xs ys)
Concatène deux listes.
(append '(1 2) '(3 4)) → (1 2 3 4)
(reverse xs)
Inverse l'ordre d'une liste.
(reverse (iota 4)) → (3 2 1 0)
(map f vs)
Applique f à chaque élément de la liste.
(map (lambda (x) (* x 2)) '(1 2 3)) → (2 4 6)
(filter pred xs)
Garde les éléments qui satisfont le prédicat.
(filter (lambda (x) (> x 2)) '(1 2 3 4)) → (3 4)
(zip vs ws)
Combine deux listes en paires.
(zip '(a b) '(1 2)) → ((a 1) (b 2))
(foldl f init xs)
Réduction gauche (fold left).
(foldl (lambda (a x) (+ a x)) 0 (iota 100)) → 4950
(foldr f init xs)
Réduction droite (fold right).
(foldr (lambda (x a) (cons (* x 2) a)) () '(1 2 3)) → (2 4 6)
(compose f g)
Compose deux fonctions : retourne λx. f(g(x)).
((compose car cdr) '(1 2 3)) → 2
(deriv f h)
Dérivée numérique : retourne une approximation de f'.
((deriv (lambda (x) (* x x)) 0.001) 3) → 6.000
(any pred xs)
Un des éléments satisfait-il le prédicat ?
(any (lambda (x) (> x 5)) '(3 7 2)) → 1
(all pred xs)
Tous les éléments satisfont-ils le prédicat ?
(all (lambda (x) (> x 0)) '(1 2 3)) → 1
📚 prolog.lisp = votre stdlib : chargé au démarrage comme un init.lisp
ou un .bashrc. Définit les primitives de base — map, filter,
foldl — qui servent de fondation à tout le reste.
☕ Ce langage a été écrit en C, avec amour, un peu de sueur,
et une quantité non négligeable de malloc.
Il tourne sur votre machine. Vous pouvez littéralement parler à l'OS en LISP maintenant.
Profitez-en pour frimer à la machine à café.