Janet pour le commun des mortels (2023)
(ianthehenry.com)- Janet for Mortals est un livre en ligne gratuit consacré au langage de programmation Janet, mais cette rétrospective porte davantage sur le processus de création d’un ouvrage technique incluant un REPL web et des projets d’exemple que sur le livre lui-même
- L’ensemble du travail a pris 20 semaines ; l’estimation initiale de 12 semaines pour la seule écriture a été dépassée par des tâches annexes comme le site web, les bindings C++, les démos dans le navigateur, le parseur de CLI et les outils de test
- Le site du livre propose un REPL intégré utilisant la grammaire CodeMirror et Lezer ; l’autocomplétion interroge l’environnement Janet via WebAssembly, et
(report)enregistre les retours dans SQLite cmd,judge,to doet Toodle.Studio servent de cas de base montrant que Janet peut être utilisé pour le scripting, les outils CLI, les tests, l’exécution dans le navigateur et l’interopérabilité JavaScript- Juste après le lancement, les seules soumissions à Hacker News et Lobsters ont attiré 30 025 visiteurs uniques le vendredi, 9 568 le samedi et 3 777 le dimanche, mais le nombre d’IP uniques ayant lu au moins 5 chapitres est estimé à 387
Périmètre du livre et charge de travail réelle
- Janet for Mortals est un livre en ligne gratuit consacré au langage de programmation Janet
- La production complète a pris 20 semaines, sur du temps libre
- L’estimation initiale était de 12 semaines et, si l’on ne considère que le temps de rédaction du texte anglais, elle n’était pas très loin
- Le calendrier réel a été largement occupé par des projets de code autour du livre
- Le volume final est de 44 000 mots de prose anglaise, hors extraits de code
- À titre de comparaison, The Great Gatsby compte 47 000 mots
- C’est moins de la moitié de la longueur de la précédente série d’articles sur Nix
- Sur 5 mois, les travaux suivants ont aussi été menés en parallèle du livre
- Le site du livre
jimmy: bindings pour une bibliothèque C++ de structures de données persistantes- Toodle.Studio : un terrain de jeu interactif de turtle graphics
cmd: une bibliothèque de parsing d’arguments en ligne de commandejudge: un framework de tests par snapshots inlineto do: un gestionnaire de tâches en ligne de commande
Le site web et le REPL intégré
- Le dispositif central du site Janet for Mortals est le REPL intégré
- L’utilisateur peut ouvrir le REPL à tout moment avec la touche Échap
- Le REPL est fixé en bas de la page et ne masque pas trop le texte
- L’éditeur utilise CodeMirror
- CodeMirror ne prend pas Janet en charge par défaut
- Le support du langage Janet créé auparavant pour Bauble a servi de base
- Des éléments de syntaxe Janet comme les chaînes
multi`backtick`quoted, peu importants dans le DSL de Bauble, étaient nécessaires dans le livre
- En enrichissant la grammaire Lezer utilisée par CodeMirror, la même grammaire a aussi été réutilisée pour la coloration syntaxique des extraits de code du livre
- Aucun générateur de site statique connu ne semblait prendre en charge la coloration de code Janet
- Au départ, le livre était en noir et blanc, mais des couleurs ont été ajoutées pour rendre la syntaxe Janet, peu familière, plus accessible
- Le générateur de site statique a été écrit sur mesure avec
redo- Le cœur du générateur était écrit en JavaScript, ce qui permettait d’y brancher la grammaire Lezer
- L’ensemble reposait sur une architecture fragile, assemblée avec du shell
- Remark est utilisé à la fois pour parser le texte source du livre et dans le REPL côté client
- Une petite extension permettant d’ajouter des labels aux blocs de code a été ajoutée
- Les docstrings de la bibliothèque standard Janet étant écrites en Markdown, elles sont rendues en HTML à la volée dans l’autocomplétion du REPL
Autocomplétion et retour unidirectionnel
- L’autocomplétion du REPL a été traitée comme un point important pour les lecteurs découvrant Janet
- Au démarrage du REPL, l’environnement Janet est interrogé dynamiquement via WebAssembly
- Même si l’utilisateur définit un nouveau symbole avec une docstring, il n’apparaît pas dans les résultats d’autocomplétion
- Il serait possible de régénérer l’autocomplétion après chaque exécution de commande, mais cela n’a pas été jugé suffisamment utile
- La fonction
(report)prend une chaîne, l’envoie en POST à un petit serveur web, qui l’enregistre ensuite dans une base SQLite- C’est proche d’une boîte de commentaires, mais avec l’envoi direct depuis le REPL comme particularité
- Cette fonctionnalité a permis de lire des retours et de corriger plusieurs erreurs
- Aucun moyen de répondre n’a été implémenté
- Le backend de report n’est pas en Janet, mais une petite application Haskell
- Son seul rôle est de recevoir les requêtes POST et de les insérer dans une base SQLite
- Le serveur web n’a pas été écrit en Janet
- La sécurité est considérée comme l’élément le plus important d’un serveur web
- Janet et ses bibliothèques HTTP n’ont pas été jugés suffisamment éprouvés pour être exposés directement à Internet
jimmy : expérimentation d’interopérabilité C++
jimmyest un binding Janet pour immer- immer est une bibliothèque de structures de données persistantes
- Le binding n’a pas été terminé et ne le sera probablement pas avant qu’un besoin concret n’apparaisse
- Il a néanmoins été considéré comme un exemple réussi pour montrer comment interopérer avec du code C++ depuis Janet
Toodle.Studio et Janet dans le navigateur
- Bauble est un petit terrain de jeu artistique créé auparavant, et la première expérience d’intégration de Janet dans le navigateur
- À l’époque, il existait peu de ressources sur l’embarquement de Janet
- Il fallait utiliser ensemble WebAssembly, Emscripten et TypeScript dans le navigateur, ce qui rendait la tâche difficile
- Le résultat final de Bauble était un site web dont la logique applicative était écrite en Janet
- L’UI utilisait beaucoup JavaScript, mais la logique centrale était assurée par Janet
- L’envie de rendre plus accessible l’usage de Janet dans le navigateur a été l’une des motivations importantes pour écrire le livre
- Dans le livre, Toodle.Studio a été créé comme exemple à la place de Bauble
- Bauble était sans état et proche d’une fonction pure transformant une chaîne en une autre chaîne, ce qui le rendait simple du point de vue de l’interopérabilité
- Toodle.Studio est clairement un fork de Bauble, mais l’interopérabilité entre JavaScript et Janet y est plus complexe
- Toodle.Studio possédait des éléments techniques plus adaptés comme exemple pour le livre
- Un programme Janet de longue durée doit être exécuté de manière asynchrone au fil du temps
- Le code JavaScript conservant plusieurs références vers les mêmes valeurs Janet, la gestion mémoire doit être prise en compte
- Des structures de données imbriquées complexes doivent être échangées avec Janet en passant par C++
- Le logo de Toodle.Studio est une tortue animée créée avec Bauble
- Elle a été ajoutée après un retour signalant qu’il s’agissait d’une démo de turtle graphics sans tortue
- Les yeux ont été conçus pour suivre la souris
cmd : parseur d’arguments CLI pour Janet
cmdest une bibliothèque de parsing d’arguments en ligne de commande- Dans le livre, elle n’apparaît que sur environ trois paragraphes, mais elle était nécessaire pour montrer clairement que Janet est un bon langage de scripting
cmdest fortement inspiré duCore.Commandd’OCamlCore.Commandest considéré comme la meilleure bibliothèque de parsing d’arguments en ligne de commande utilisée jusqu’ici- L’objectif était de reproduire cette expérience dans Janet
cmdn’est pas aussi bon queCore.Command- Avec des types, tout devient beaucoup plus simple
- Il couvre néanmoins 95 % des fonctionnalités jugées importantes, et sa notation concise le rend plus pratique pour des scripts ad hoc
- La génération de fonctions d’autocomplétion Bash manque encore
Core.Commandles génère automatiquement- L’API de
cmdest conçue pour pouvoir ajouter cette fonctionnalité plus tard
judge : framework de tests par snapshots inline
judgeest l’un des premiers outils créés en Janet en 2021- Après avoir mieux appris Janet, il a été réécrit depuis zéro
- L’API est devenue plus agréable à utiliser
- L’implémentation est aussi beaucoup plus simple et facile à modifier
- Les principales différences entre Judge v1 et v2 concernent l’emplacement des tests et les helpers
- Les tests peuvent se trouver non seulement dans le répertoire
test/, mais aussi dans les fichiers source ordinaires - Les helpers
test-macroettest-stdoutont été ajoutés
- Les tests peuvent se trouver non seulement dans le répertoire
- L’approche équivalente à
test-stdouten OCaml est décrite comme presque la seule méthode utilisée pour écrire des tests dans un contexte professionnel- OCaml n’offre pas vraiment de bonne manière d’embarquer des données arbitraires dans le code source, d’où une approche consistant à tout convertir en chaînes
- Après la publication du livre, un mode
--interactivea été ajouté à Judge- Le livre contient un chapitre sur les tests et le débogage avec Judge
to do : un outil de tâches écrit en Janet plutôt qu’en Bash
to doa été choisi comme exemple pour le chapitre sur le scripting- C’était un outil non trivial auparavant écrit en Bash, et l’implémentation Bash était pénible
- Les parties particulièrement difficiles en Bash étaient le parsing de texte et la gestion des dates
- Parser du texte multiligne avec Sed n’était pas agréable
- Manipuler
datede manière identique sur macOS et Linux est considéré comme pratiquement impossible
- En Janet, avec PEG,
shetcmd, il a été possible de créer plus de fonctionnalités, plus rapidement, que dans la liste de tâches Bash d’origine- Par exemple, la sélection multiple avec
fzfa été ajoutée - Construire des chaînes terminées par null en Bash est considéré comme difficile
- Par exemple, la sélection multiple avec
- Le livre ne traite qu’une version simplifiée
- Pas de fonctionnalité de planification future
- Pas de concept de tâche « sautée »
- Les fonctions essentielles sont l’ajout d’éléments à la liste et leur marquage comme terminés
- Utilisée avec
zsh-autoquoter, l’application est jugée étonnamment utile
Travail de code et maintenance pendant la rédaction
- Sur les 20 semaines de travail du livre, la programmation a représenté presque la moitié
- 8 semaines ont été consacrées au code, certaines périodes mêlant rédaction et développement
- Au départ, seules l’amélioration de Judge et l’écriture d’un parseur d’arguments étaient prévues
- L’implémentation du parseur d’arguments s’est révélée bien plus difficile que prévu
- Bauble était trop simple, et il n’était pas prévu de devoir créer un nouveau terrain de jeu artistique
- La rédaction proprement dite s’est faite en Markdown dans Sublime Text
- Sublime Text est l’éditeur préféré pour écrire de longues proses
- Pendant la rédaction, 2 nouvelles versions de Janet sont sorties
- Les chapitres sur le débogage et les modules natifs ont dû être mis à jour pour suivre les changements du langage
- Le livre doit être maintenu en phase avec les dernières versions de Janet
Réactions au lancement et niveau de lecture
- La promotion du livre s’est limitée à une soumission sur Hacker News, une soumission sur Lobsters et un tweet
- Sur Hacker News, il est resté toute la journée en page d’accueil et a occupé la première place pendant un moment
- D’après les logs d’accès Nginx, les visiteurs uniques étaient les suivants
- Vendredi : 30 025
- Samedi : 9 568
- Dimanche : 3 777
- Ces chiffres correspondent plutôt au nombre de personnes ayant cliqué sur le lien ; le nombre de personnes ayant réellement lu le livre est jugé bien inférieur
- Le site ne dispose pas d’analyse comportementale côté client
- L’estimation repose seulement sur les logs d’accès
- Le flux de visites des chapitres semblait montrer une rétention faible
- Le chapitre 1 représentait 22 % des visites de la page d’accueil
- Le chapitre 2 représentait 20 % des visites du chapitre 1
- Le chapitre 3 représentait 69 % des visites du chapitre 2
- Le chapitre 4, « Pegular Expressions », et le chapitre 9, « Xenofunctions », ont reçu plus de visiteurs que le chapitre 3
- À la fin du week-end de lancement, la meilleure estimation du nombre réel de lecteurs était de 387
- Elle repose sur le nombre d’IP uniques ayant chargé au moins 5 chapitres différents
Origine du nom et limites révélées par les retours
- Le nom du langage Janet vient de Janet, l’être immortel de The Good Place
- Comme cet être aide les mortals à se déplacer dans l’au-delà, cela fait aussi le lien avec le titre du livre
- Le chapitre le moins visité était « Testing and Debugging »
- C’est l’avant-antépénultième chapitre du livre
- Les trois derniers chapitres sont considérés comme les plus intéressants du livre
- La méthode de test présentée dans ce chapitre est jugée comme l’un des plus grands gains de productivité de la carrière d’ingénieur de l’auteur
- La fonctionnalité report du REPL intégré a reçu 494 retours
- Beaucoup étaient des messages du type « bon livre » ou des messages de test
- Des dizaines signalaient des fautes de frappe, demandaient des explications ou apportaient des commentaires utiles
- Certains utilisateurs ont envoyé des questions sans coordonnées, et l’absence de fonction de réponse a empêché d’y répondre
- La fonction report a été implémentée comme un mécanisme de retour unidirectionnel très rudimentaire
1 commentaires
Avis sur Hacker News
Il ne faut pas non plus passer à côté de https://bauble.studio/ du même auteur
Ça ne fonctionne pas dans le navigateur de mon vieil ordinateur, mais quand j’étudie à la bibliothèque et que j’ai envie de faire une pause, il m’arrive de jouer avec bauble pendant une trentaine de minutes sur un ordinateur de la bibliothèque
C’est impressionnant de voir tout ce qu’on peut créer comme graphismes simplement en changeant quelques nombres, et j’espère que Janet durera longtemps
unknown symbol twisterror: script:16:1: compile error: unknown symbol twistin evaluate [lib/evaluator.janet] on line 81, column 7in bauble-evaluator/evaluate [lib/init.janet] on line 8, column 12Il est intéressant de comparer Janet à GNU Guile
L’atout d’origine de Guile, c’était d’être conçu comme un langage facile à utiliser aux côtés du C, mais comme c’est un vieux langage, il ne semble pas encore avoir adopté une approche plus moderne consistant à inclure par défaut un gestionnaire de paquets dans la toolchain du langage
Ce que j’apprécie chez Guile, c’est l’effort important consacré à expliquer sa compatibilité avec les standards RNRS
Je ne sais pas à quel point Janet est vraiment proche de Scheme, mais ça m’intrigue
C’est plus proche de quelqu’un qui aurait créé Clojure au-dessus de Lua
Le livre est ici : https://janet.guide/ et le langage est là : https://janet-lang.org/
J’ai aimé l’approche pratique de ce livre, et c’est en grande partie pour ça que j’apprends Janet en résolvant Everybody Codes en Janet en ce moment
https://everybody.codes
La formule « la tortue est une métaphore » me déçoit un peu
La tortue n’était pas une métaphore, elle était réelle : http://classicacorn.computinghistory.org.uk/8bit_focus/logo/...
Bien sûr, cela correspond à la définition d’une métaphore comme « quelque chose qui représente autre chose, un symbole », mais ça fait penser à la blague sur quelqu’un qui prend l’icône de sauvegarde en forme de disquette pour un réfrigérateur
J’ai l’impression qu’il manque le contexte : il existait réellement autrefois de mignonnes tortues matérielles amusantes
Rien qu’au titre, je pensais que c’était encore un assistant IA inspiré de Janet dans The Good Place, mais c’était en fait un langage de programmation, et ça a été une bonne surprise
Le langage Janet tient son nom de Janet, l’être immortel de The Good Place qui aide les humains à se repérer dans l’au-delà, donc le titre est aussi un jeu de mots bien trouvé
J’ai aussi été surpris qu’il fournisse PEG (grammaires d’expression syntaxique) en plus du moteur d’expressions régulières par défaut
J’ai toujours souhaité que les langages qui fournissent une bibliothèque regex de base incluent aussi un vrai PEG
Voir <https://www.gnu.org/software/guile/manual/html_node/PEG-Pars...>
sporkde Janet occupe un rôle un peu comparable à une libc, et il comprend aussi un sous-module regex, donc il y a de fortes chances qu’il soit installéJ’ai découvert les PEG avec Janet, et j’aime leur puissance et leur facilité d’utilisation
Cela fait plus de 20 ans que je touche un peu aux regex, et pourtant j’ai mieux compris les PEG en quelques mois
Il y a aussi beaucoup de clins d’œil à The Good Place dans la communauté Janet, et plusieurs modules tiers portent le nom de personnages de la série
elm/regexetelm/parserne sont pas intégrés par défaut, maiselm/regexrecommande à la place d’utiliser elm/parserJ’aime bien l’origine du nom, mais un langage qui s’appelle Janet semble aussi avoir le devoir de privilégier le contrôle
J’ai lu le livre, et je l’ai trouvé assez intéressant et joueur, ce qui a rendu l’apprentissage de Janet bien plus amusant
En revanche, la documentation du langage laissait à désirer sur plusieurs points
Il arrivait souvent que des fonctions ou des commandes soient simplement listées, sans exemple ni explication, voire sans même indiquer ce qu’elles faisaient
Il y a aussi eu souvent des fonctionnalités vues dans le livre que je n’arrivais pas à retrouver dans la documentation, et c’est l’une des raisons pour lesquelles, malgré mon affection pour Janet, j’ai fini par arrêter de l’apprendre
J’aime le fait qu’il y ait beaucoup de choix par défaut raisonnables et des ressemblances avec les langages grand public plutôt qu’un attachement obstiné aux vieilles conventions Lisp
Au final, comme ce ne sont pas des listes cons, ce n’est pas vraiment du Lisp, mais ça me va
Le problème, c’est simplement que le langage n’est pas assez documenté
Je suis un peu actif dans la communauté Janet, donc si je connais les manques, je peux contribuer à améliorer la documentation
Parfois, il n’y avait que la signature d’une fonction, sans la moindre explication supplémentaire
Je sais bien que produire une documentation riche demande beaucoup de temps et d’efforts, mais cela arrivait si souvent que j’ai fini par laisser tomber et chercher un autre Lisp compilé en binaire
Je n’ai jamais vraiment réussi à m’adapter à Janet, mais je ne sais pas si le problème vient de moi
Le seul autre Lisp que j’ai utilisé longtemps est Emacs Lisp, et Janet lui ressemble suffisamment tout en étant subtilement différent, ce qui me fait sans cesse commettre de petites erreurs
Les fonctionnalités PEG semblaient séduisantes dans la documentation, mais j’ai trouvé la syntaxe pénible à manipuler et déroutante
La documentation était complète au sens où toutes les fonctions y étaient décrites, mais elle restait très succincte, avec peu d’exemples ou d’informations d’usage utiles
Il ne semblait même pas y avoir de fonctions de base comme le parsing JSON
Si, dans un langage censé servir à écrire rapidement des scripts, je dois d’abord écrire mon propre parseur JSON ou XML, alors c’est déjà une tâche ratée
Cela remonte à environ quatre ans, donc l’écosystème s’est peut-être amélioré, ou alors mes critères d’évaluation de Janet comme langage de script n’étaient pas les bons
Malgré tout, ce billet me donne envie de le réinstaller
spork, qui joue un peu le rôle d’une libcIl y a une forte volonté en interne de garder le cœur léger
Beaucoup de projets dépendent de
spork, donc il y a de fortes chances qu’il soit installé dès le départLa documentation est plutôt correcte, mais je suis d’accord qu’il reste des lacunes sur les exemples pratiques
https://janetdocs.com comble en partie ce manque, avec des liens vers des « exemples de la communauté » pour chaque fonction
Hors sujet, mais c’est grâce à un autre billet du blog original que je me suis mis aux claviers mécaniques séparés
Ça m’a aidé pour des douleurs d’épaule et de poignet que j’avais depuis des années, et je recommande vivement de lire aussi les autres billets de Ian
Le choix d’ouvrir à tout moment un REPL intégré fixé en bas en appuyant sur
Escn’est peut-être pas une bonne idéeLe navigateur a déjà un raccourci par défaut sur
Esc, et Firefox quitte le plein écran quand on appuie surEsc