Il y a trois semaines j'ai décidé d'apprendre Common Lisp, motivé principalement par la curiosité et attiré par l'approche assez différente de la programmation qu'a Common Lisp par rapport à des langages d'autres familles. Je vous raconte ma vie, des fois que vous ayiez aussi envie d'apprendre ce langage et vouliez gagner du temps avec les premier pas.
Mon profil. Je suis mathématicien de formation (cursus math/info, calcul scientifique puis géométrie algébrique) et je travaille depuis 6 ans avec beaucoup de programmation dans des rôles variés – et je programmais déjà auparavant en hobby. Je connais pas mal de langages (OCaml, C, Bourne Shell, JavaScript, TeX) et j'ai déjà écrit des programmes substantiels dans d'autres langages (C++, Python 2.X, perl, PHP, assembleur 8086) donc je ne suis plus tout à fait un débutant en programmation. (Surtout des simulations numériques, du GUI, du traitement de données géographiques, de l'automatisation de traitement de Cloud, des traitements de données.)
Mon premier environnement. J'ai choisi d'utiliser SBCL, une implémentation libre largement disponible sur les systèmes actuels et Emacs/SLIME comme environnement de développement. Dans Emacs la commande slime
permet de démarrer une boucle d'évaluation, ce qui est suffisant pour commencer à expérimenter.
Mon premier livre pour Common Lisp. Après avoir évalué les ressources suggérées sur reddit j'ai décidé de prendre le livre de Paul Graham, ANSI Common Lisp. Je l'ai préféré à un autre choix apparemment populaire, le livre de Peter Seibel Practical Common Lisp parceque ce dernier ne propose pas systématiquement des exemples complets (il utilise beaucoup de “supposons que f soit une fonction qui fasse ceci-cela”) alors que Graham ne donne que des exemples qu'on peut réellement utiliser dans la boucle d'évaluation, ce qui est très chouette pour expérimenter et apprendre de façon interactive. A posteriori je suis encore plus content de ce choix parceque le livre de Graham peut aussi être utilisé comme référence, par exemple si on veut se remettre en mémoire les détails de la façon de définir une fonction il suffit de relire le chapitre “Fonctions.” De ce côté là le livre de Seibel est un peu moins pratique mais c'est néanmoins une seconde lecture très recommendable. Le livre de Graham n'est pas trop recommandé pour les débutants en programmation, notamment à cause de son utilisation de mnémoniques un peu abstruses pour nommer les variables et les fonctions, ce qu'on considère aujourd'hui comme un exemple à ne pas suivre.
En me prenant une demi-journée par jour et en faisant un peu de rab le week-end, il m'a fallu une grosse semaine pour faire le tour du livre.
Le seul gros défaut du livre de Graham est qu'il manque quelque peu d'exemples substantiels. Dans le cœur du livre le seul gros exemple est un petit ray tracer – c'est assez fun! Dans les derniers chapitres, il y a un petit système de déductions formelles, un générateur de HTML (cela fait délicieusement rétro aujourd'hui) et une implémentation de la logique objets (le method dispatching). Un des meilleurs livres est le livre sur “Le langage Caml” qui présente plein d'exemples ambitieux (compression de données, mini machine virtuelle, un assembleur et un compilateur Pascal pour n'en citer que quelques uns!)
Aprés le livre. Une fois les bases connues, il est grand temps d'affiner ses connaissances! Des pistes à explorer toutes en même temps sont l'essai de bibliothèques, la lecture de leur code, l'apprentissage de SLIME, notamment grâce à la vidéo de Marco, puis de quicklisp et l'organisation d'un projet (voir les exemples de bibliothèques sur par GitHub et dans la base quicklisp).
Pour ma part je me suis arrêté sur JSCL un compilateur Lisp vers JavaScript et je voudrais y ajouter une intégration de React, pour pouvoir programmer des GUIs React en Lisp.
Amusez-vous bien!
# C'est pas common
Posté par YBoy360 (site web personnel) . Évalué à 5.
Mais c'est bien!
Comme disait Pierre Dac :
# Lisp + React
Posté par Adrien BUSTANY (site web personnel) . Évalué à 3.
C'est pas un peu ce que fait https://github.com/omcljs/om avec ClojureScript ?
[^] # Re: Lisp + React
Posté par Michaël (site web personnel) . Évalué à 4.
Apparemment oui, mais il ne faut pas oublier que Clojure est un dialecte de Lisp, donc la syntaxe est légèrement différente,.
[^] # Commentaire supprimé
Posté par Anonyme . Évalué à 2. Dernière modification le 14 octobre 2017 à 06:35.
Ce commentaire a été supprimé par l’équipe de modération.
[^] # Re: Lisp + Ecma
Posté par Michaël (site web personnel) . Évalué à 4. Dernière modification le 14 octobre 2017 à 16:41.
Entre dire que JavaScript est plus proche de Lisp que de Java et dire que c'est un dialecte de Lisp, il y a quand-même un petit monde que je ne franchirais pas! Au-delà de la syntaxe toute différente, les différences notables sont:
La méta-programmation, où on a du côté de JavaScript des possibilités d'introspection très développées et une fonction
eval
(qu'on essaie de ne pas utiliser) et de celui de Lisp un système de macros très solide, avec notammentloop
etdo
.Des approches assez différentes pour la programmation par objets.
La portée des variables obéit à des mécanismes différents: le variable hoisting, le mot-clef this et la seule portée lexicale des variables pour JavaScript le distinguent de Lisp.
En revanche. un gros point commun de Lisp et JavaScript, est l'accent très fort mis sur les structures de données et l'interactivité, ce qui pousse assez naturellement le programmeur à écrire des fonctions très découplées des autres, très faciles à tester.
Le livre de Crockford, auteur de l'article que tu cites, est une excellente introduction à JavaScript.
# Petite parenthèse...
Posté par Elfir3 . Évalué à 5.
Merci pour ces quelques pistes pour commencer. Tu m'as donné envie de me joindre à l'aventure même si ce n'est pas pour tout de suite : je viens de commencer un projet dans un autre langage. Je garde ton journal en mémoire.
Par contre on sent que tu débutes, tu as encore des paragraphes sans parenthèses ;-)
Bon courage dans ton aventure !
(Et ne t'inquiète pas, même après 12-13 ans d'utilisation intensive d'emacs, mes doigts se portent encore plus ou moins bien..)
# Oui mais non
Posté par dzecniv . Évalué à 4.
Salut,
ravi de lire cela, moi-même investissant du temps pour découvrir le langage et son écosystème (cf mon journal https://linuxfr.org/users/dzecniv/journaux/decouvrons-common-lisp-comparaison-avec-l-environnement-python)
Mais tu n'y es pas du tout ! Google n'est toujours pas bon en CL donc on doit le nourrir à la becquée. Il faut rediriger vers http://lisp-lang.org/ pour mettre l'eau à la bouche aux lecteurs et lectrices, puis citer https://github.com/CodyReichert/awesome-cl pour éventuellement évoquer Cliki (j'aime pas Cliki). Ensuite moi je cite toujours le Common Lisp Cookbook, la version sur github, vachement améliorée cette année.
Ensuite as-tu vu Panic, une preuve de concept qui fait marcher React ?
Pour ce qui est d'un framework web "dynamique", je parie et m'intéresse fort à Weblocks. Mais à la version d'un dév en train de le factoriser et moderniser, dont l'exemple pour faire un TodoMVC est très clair et très simple: http://40ants.com/weblocks/quickstart.html On construit donc une page interactive en pure lisp, sans écrire d'appels Ajax, où ils sont backportés en pur html si besoin, avec l'avantage d'un environnement Lisp (détection d'erreurs, debuggeur, création d'un exécutable,…). Mon idéal en passe de se réaliser c'est de coder une app web en un langage, avec la même expérience de dév et débug par conséquent, de construire des exécutables prêts à être déployés, d'explorer leur runtime en live, de déployer "à chaud" et de fournir une version de bureautique via Electron (Ceramic en CL). On y est quasiment !
Fais-nous part de tes avancées par ici !
ps: cf aussi mon tuto en cours de finition (web scraping, création d'exécutables, tests,…)
pps: vidéo de Marco illisible "fichier corrompu" :(
[^] # Re: Oui mais non
Posté par Michaël (site web personnel) . Évalué à 2.
Merci pour toutes ces précisions. J'avais vu Weblocks, Panic et Parenscript
L'impression que m'a fait Weblocks est qu'il implémente l'état de l'art de la programmation web d'il y a environ 5-10 ans – ce qui est très impressionnant mais on s'en est aujourd'hui largement détourné. Est-il exact que le modèle proposé par Weblocks produit un couplage très fort entre l'UI, la logique de l'application et la base de données? Si c'est le cas c'est précisément le modèle dont on s'est radicalement éloigné ces dernières années, en faisant une UI qui communique avec des microservices via une API explicite (p.ex. en signant les requêtes, ce qui dans certains cas élimine pratiquement le besoin de maintenir une session, ce qui simplifie beaucoup la logique de l'application!), ce qui permet d'utiliser les fonctions de l'application web en RPC JSON/HTTPS et permet aux développeurs de la GUI et ceux de l'application de travailler de façon complètement découplée. (Notamment en testant les composants de la GUI avec des storybooks au lieu de devoir accéder à un environnement complet.)
Ceci dit Weblocks semble très impressionnant – et ma première impression est peut-être fausse. La documentation que tu proposes en lien ne va pas beaucoup plus loin que l'exemple minimal de la TODO liste, est-ce que tu as d'autres lectures sur Weblocks à recommander?
[^] # Re: Oui mais non
Posté par dzecniv . Évalué à 2.
Non malheureusement pas d'autres lectures sur Weblocks à proposer, l'ancien site n'a pas grand chose.
Effectivement Weblocks produit un couplage comme tu l'as décrit, mais à l'inverse de ce qu'on pourrait conclure avec les exemples qui mélangent allégrement logique, template et style, on peut faire du MVC en mettant ce qu'il faut dans leurs propres fichiers et modules. Néanmoins, à ce que je comprends un bénéfice de l'approche de Weblocks serait d'écrire une app web de manière plus linéaire, grâce à son système basé sur les continuations (qui gère la session et pour lequel le développeur n'a besoin de connaître que 2 ou 3 macros).
# Perlissade
Posté par gasche . Évalué à 7.
Et alors, est-ce que Common Lisp a changé la façon dont tu penses à la programmation ?
[^] # Re: Perlissade
Posté par Michaël (site web personnel) . Évalué à 4.
Pas vraiment la façon dont je la pense mais comme programmeur OCaml expérimenté je peux dire que le cycle de développement avec Common Lisp est complètement différent de ce qu'il est avec OCaml.
La raison principale est la proximité de l'évaluation du programme avec l'écriture de celui-ci. En OCaml on peut utiliser la REPL pour mettre au point une fonction mais c'est assez compliqué à mettre en place parcequ'il faut écrire un
.ocamlinit
spécifique au projet qui charge les modules nécessaires au module où vit notre fonction et installe les pretty-printers. Si on se rend compte qu'on a besoin du débogueur, il faut refaire toute cette configuration avec le débogueur. Enfin, une fois qu'on est content de sa fonction on peut continuer la mise au point avec une autre fonction d'un autre module et cela demande d'ajuster les fichiers de configuration pour le toplevel ou le débogueur à la main. En Common Lisp tout ce petit yoga disparaît, ce qui est du à l'association du débogueur à la REPL et à la portée dynamique des variables. Ce type de développement très interactif est semble-t-il un des points forts de Common Lisp et la norme parmi les programmeurs, c'est en tout cas une façon très agréable de travailler.Même si les PPE de OCaml sont très puissants et relativement faciles à utiliser – moyennant compilation et installation, puis paramétrage de la REPL pour les utiliser, et je ne sais pas si le débogueur les prend en charge – il faut bien reconnaître que la fonction équivalente en Common Lisp fournie par les macros est, en comparaison, d'utilisation enfantine.
Un point sur lequel OCaml et Common Lisp se rapprochent est qu'en dépit de leur expressivité ces langages restent assez proches de la machine, ils laissent entrevoir très nettement les rouages de la machine.
Comme en OCaml, le code assembleur généré (ici par SBCL) est très lisible:
Un examen succinct montre que L1 est notre
if
final et le reste de la structure s'en déduit facilement. Pour une version un peu plus “bas niveau” peut être écrite en ajoutant des annotations:L'assembleur est un peu moins facile à suivre (pour moi) mais on voit quand-même que le seul appel à une fonction (remote call) est celui fait à
length
pendant l'initialisation de la boucle et que dans la boucle, la seule instruction qui accède à la mémoire est celle en positionF00
tout le reste ne consiste qu'en des opérations très rapides sur les registres et des sauts courts. À la fin on nettoie la pile – seule la partie après le IDIV reste pour moi très mystérieuse, mais la boucle critique est simple et claire, même avec mes connaissances rudimentaires en assembleur.# Je déteste CL
Posté par foobarbazz . Évalué à 3.
Je déteste CL. C'est une horreur, l'une des pires choses qui soient arrivé à lisp et à la programmation fonctionnelle.
Lisp, c'est super beau, on est d'accord. Mais les lisp-1 sont beaux, pas les 2 ! Pour les non lispeurs, la différence c'est la porté des variables. Elle est syntaxique sur les lisp-1, et FUCK YOU sur les lisp-2. Il y a aussi la manière dont sont traitées les fonctions, comme n'importe quelle autre valeur sur les lisp-1, et comme FUCK YOU sur les lisp-2.
Après, il y a la lib… La convention de nommage utilisée c'est FUCK YOU (plus les exemples précis en tête, mais la convention de de préfixer les fonctions non pures par un "n" n'est pas systématiquement utilisée).
Après, il y a les macros, et les horreurs qu'on peut faire avec… Genre… Tiens, pourquoi pas faire de la Programmation Orientée Objet (💩) ? Et vous vous retrouvez avec un clusterfuck de méta programmation… Je vous laisse deviner la super méthode pour déboguer tout ça, ça commence par un F.
Bref:
Lisp, oui.
Common Lisp, non.
[^] # Re: Je déteste CL
Posté par theor . Évalué à 1.
La difficulté, c'est que les très beaux langages comme Scheme, GNU Guile… ont une utilité limité pour écrire des programmes génériques, on est plus dans la preuve de concept ou l'outil de théoricien. Ce que je regrette.
CL est comme le C++ : atroce, "méta", complexe, plein d'inconsistances et de subtilités, mais tu écris ce que tu veux avec.
Bon, on me fera remarquer que Scheme, c'est comme le C : un langage pur, minimaliste, puissant. Sauf qu'en C, on trouve des bindings pour tout (GTK, boites à outils…), en Scheme, rien. Et la performance n'est pas la même non plus.
[^] # Re: Je déteste CL
Posté par Lizzie Crowdagger (site web personnel) . Évalué à 5.
Niveau Scheme, il y a Racket, où il me semble qu'il y a quand même pas mal de choses de disponibles.
Perso, je m'étais pas mal intéressée à Clojure, mais autant l'intégration à la JVM peut être un avantage pour utiliser plein de bibliothèques Java sans (trop) se prendre la tête, autant ça limite aussi si tu préférerais plutôt proposer un « vrai binaire » (notamment, je sais pas si ça a a évolué dernièrement, mais les temps de lancement étaient assez rédhibitoires à mon goût pour un programme en ligne de commande qui est censé s'exécuter plus ou moins instantanément).
[^] # Re: Je déteste CL
Posté par Dr BG . Évalué à 7.
Quelles implémentations recommandes-tu ?
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.