Boring languages win

L'IA se plante deux fois plus en JavaScript qu'en Java. Le problème c'est pas le modèle, c'est le langage.

· 1 min de lecture ·
iacraftlangages

Python est le langage le plus utilisé pour faire de l’IA. C’est aussi un des pires langages pour l’IA qui code.

En 2022, une équipe a testé Copilot sur 33 problèmes LeetCode dans quatre langages. Java : 57% de code correct. JavaScript : 27%. Même modèle, même benchmark. La seule variable, c’est le langage. Les modèles ont beaucoup progressé depuis. L’écart entre langages, par contre, persiste.

En mars 2026, une étude teste Gemini 2.5 Flash sur la génération de suites de tests. Résultat : 2 155 tentatives en Python pour arriver à une suite correcte, contre 323 en Java. Presque 7 fois plus de tours pour converger. C’est pas juste un taux d’erreur, c’est une friction de base qui se propage sur tout le workflow.

Go, que sa propre communauté revendique comme ennuyeux, est celui où l’IA se plante le moins.


“C’est le training data”

L’objection vient tout de suite. Java a un corpus énorme sur GitHub, du code enterprise bien testé, bien documenté. Normal que les modèles soient meilleurs en Java.

Sauf que Python aussi a un corpus énorme. PyPI, data science, notebooks Jupyter, tout StackOverflow. Si le volume de données d’entraînement expliquait tout, Python devrait scorer en haut. Il est en bas.

JavaScript a plus de données que Go. Et les agents produisent du Go valide en one-shot 95% du temps.

Le volume de données joue, mais pas comme on le pense. Le corpus détermine quel pattern le LLM va choisir : le plus fréquent. La sémantique du langage détermine combien de patterns sont valides. Dans un langage boring, y’a un seul chemin, donc le plus fréquent est aussi le bon. Dans un langage expressif, le plus fréquent c’est pas forcément le plus adapté au contexte. Le training data ne rend pas le LLM meilleur sur un langage. Il détermine quel chemin le LLM prend quand il y en a plusieurs.


Ce que “expressivité” veut dire

Prenons un truc simple : filtrer les nombres pairs dans une liste.

En Go, y’a une façon de le faire. Une boucle for, un if, un append. Tout le monde écrit le même code. gofmt impose le formatage. Y’a rien à deviner.

En Python, y’a au moins trois façons :

# list comprehension
pairs = [x for x in nombres if x % 2 == 0]

# filter + lambda
pairs = list(filter(lambda x: x % 2 == 0, nombres))

# boucle for classique
pairs = []
for x in nombres:
    if x % 2 == 0:
        pairs.append(x)

Les trois sont du Python valide. Y’en a d’autres (generator expressions, numpy…). La list comprehension est “idiomatique”. La boucle for est “trop verbose”. Mais pour un LLM, la boucle for est la plus prévisible des trois.

L’expressivité, c’est ça : le nombre de chemins pour arriver au même endroit. Pour un humain expert, c’est de la puissance. Moins de code, plus dense, plus élégant. Pour un LLM, chaque chemin en plus c’est un endroit où se tromper.

L’expressivité, c’est du DRY poussé loin. Les langages expressifs ont été conçus pour résoudre un problème humain : la répétition. Écrire moins, abstraire plus, ne jamais se répéter. Le LLM n’a pas ce problème. Écrire 10 fois le même pattern ne le fatigue pas. Mais choisir entre 5 façons de ne pas se répéter, ça le rend confus. Il n’a pas de préférence, juste des probabilités. Cinq options valides c’est cinq probabilités proches, et il prend la plus fréquente, pas la plus adaptée.

Paul Graham défendait l’expressivité comme une arme secrète. Dans Beating the Averages, il expliquait que Lisp lui donnait un avantage concurrentiel parce que ses concurrents ne pouvaient même pas voir ce qui leur manquait. Le “Blub Paradox” : le programmeur moyen regarde un langage plus expressif et voit des trucs bizarres, pas de la puissance.

Rob Pike a pris le contre-pied exact en créant Go. “Less is exponentially more.” Go est conçu pour que le code soit lisible par les autres, pas pour que l’auteur se sente puissant.

Les deux avaient raison. Mais pas pour le même utilisateur. L’humain expert profite de l’expressivité. Le LLM profite de la contrainte.

Permissif → Strict
Fiable pour l'IAStrict mais coûteuxImprévisible pour l'IASimple mais risqué
Go
Java
C
TypeScript
Rust
C#
Python
JavaScript
Ruby
Boring → Expressif

Ce positionnement est ma lecture des données, pas un classement mesuré. Les deux axes sont défendables (voir sources) mais les positions exactes sont subjectives.


Les cas qui testent la thèse

C est syntaxiquement pauvre. Peu de mots-clés, peu de façons d’écrire la même chose. Et les benchmarks montrent que ça aide, en partie. Mais C a un autre problème : le comportement indéfini. L’arithmétique de pointeurs, les buffer overflows, les bugs mémoire subtils. Le LLM écrit du C qui compile et qui a l’air correct, mais qui pète au runtime dans des cas limites. Être boring dans la syntaxe ne suffit pas si le langage te laisse te tirer dans le pied en silence.

Rust est le cas le plus intéressant. C’est le langage le plus strict qui existe. Le borrow checker, les lifetimes, tout est vérifié à la compilation. Si “strict = bon pour l’IA”, Rust devrait dominer. Il est au milieu. Parce que strict et boring c’est pas la même chose. Rust a un système de types très puissant, plein de façons idiomatiques de gérer un problème de lifetime. Pour le LLM, le borrow checker c’est pas un garde-fou, c’est un labyrinthe de plus à résoudre.

Graydon Hoare, le créateur de Rust, l’a dit lui-même : “I would have traded performance and expressivity away for simplicity.” Il parlait de la complexité du compilateur et du système de types, pas du nombre de façons d’écrire la même chose. Mais la direction est la même : même lui aurait préféré plus simple.

TypeScript est le cas le plus parlant. C’est JavaScript qui devient statique, en temps réel. Une étude de l’ETH Zurich (PLDI 2025) montre que forcer le LLM à respecter le système de types pendant la génération divise les erreurs de compilation par deux. Les types posent des limites. Moins de choix possibles, moins d’erreurs. Et l’adoption suit : en août 2025, TypeScript est devenu le langage #1 sur GitHub en contributeurs mensuels. 40% des devs JS écrivent exclusivement en TypeScript.

Python est deux langages en un. Le subset typé, avec mypy strict et les type hints, produit du code que les LLMs gèrent bien. Le subset dynamique, avec le duck typing et la magie, produit du code où ils se plantent. Le score moyen de Python mélange les deux. Et la tendance est nette : une enquête Meta de 2025 montre que 86% des développeurs Python utilisent les type hints. Même Python devient plus boring.


Et toi, tu fais quoi avec ça

C’est pas “change de langage”. C’est “quel que soit ton langage, écris boring”.

TypeScript strict plutôt que any. Des interfaces explicites plutôt que des types inférés. Python typé plutôt que duck typing. Le moins de magie possible. Le moins de trucs astucieux possible. Une list comprehension imbriquée c’est du Python “propre”, c’est du Python idiomatique, et c’est exactement ce qui fait planter la machine. Trois lignes avec une boucle for, c’est moche, c’est verbose, et le LLM le génère correctement du premier coup.

Et ce qui vaut pour le langage vaut pour le framework. Tout framework qui repose sur de la magie déclarative plutôt que du flux explicite pose le même problème.

Plus un framework repose sur des conventions implicites, des décorateurs, de l’injection par metadata, plus le LLM devine. Et quand il devine, il choisit le pattern le plus courant, pas le plus adapté au contexte.

Le truc, c’est que le code boring était déjà la recommandation du craft bien avant l’IA. Explicit is better than implicit. KISS. Pas de magie. On répète ça depuis des années. Ce qui change, c’est qu’on a maintenant les chiffres pour le prouver.

Le choix du langage c’est la friction de base. Y’a d’autres couches qui aident : le contexte qu’on donne au modèle, les tests, l’architecture du projet. Mais plus la première couche est expressive, plus les autres doivent compenser.


Dijkstra, 1975 : “Simplicity is prerequisite for reliability.” Les chiffres lui donnent raison.

Sources