François Pinard's site

Scheme

Table des matières

1 .

[2007-12-20 jeu] Scheme always attracted me because of its purity and elegance. Despite past excursions at using it, it never stuck in my real habits, because of its lacking libraries. I hope to find ways to enjoy it more often in the future.

2 Scheme and me

This is an old text, likely written near the end of 2007. Since then, I had a burst of Scheme activity for a projet which, for various reasons, used an old Kawa. That particular implementation had plenty of heisenbugs, which destroyed a significant part of my pleasure. My interest for Scheme survived, yet now with a much more reasonable appetite ☺.

Me voilà, à contempler Scheme encore une fois, et parmi les divers Scheme, Gambit en particulier, d'une part à cause de sa performance, de ses conditions maintenant plus libérales de distribution, et aussi à cause de l'avantage particulier que j'ai de connaître son concepteur. Scheme avec ses qualités, mais avec quelques défauts qui sont toujours là, et la curiosité assez forte que j'ai de savoir ce qu'on peut, ou pourrait y faire, dans la pratique. Mais avec le doute aussi de la conséquence néfaste qu'auront probablement, à long terme sur la communauté de ses utilisateurs, ou sur la perception du langage par l'extérieur, les disputes ou déchirements autour de R6RS (je vois dans les sources du compilateur que Gambit se prépare à le supporter).

Suite à l'expérience de mon projet Topy, je m'interroge sur l'opportunité de retenter un projet analogue en Scheme, dans le but cette fois de partiellement automatiser un traducteur de Python à Scheme, et ainsi faciliter le transport en vue de Snow de bibliothèques peut-être récupérables. En fait Topy m'a servi pour d'autres langages aussi (Perl, Scheme, Python, C) avec un succès inégal, mais je n'ose pas trop laisser vagabonder mon imagination, quoique j'ai un peu de difficulté à ne pas considérer Java. Il est difficile de prévoir la fertilité réelle d'une telle entreprise, toute attrayante qu'elle puisse sembler.

Le manuel de Gambit, qui a pris du volume depuis ma lecture précédente, demeure très laconique au sujet des namespaces. Est-il possible, pour Scheme ou Gambit, de retrouver le même agrément que Python à ce sujet? Via Google, j'ai trouvé quelques implantations d'orientation objet pour Gambit, mais sans avoir pris le temps de les comprendre ni d'évaluer leur (perte d') efficacité. Comment procéder pour évaluer tout ça et choisir la bonne?

Je constate aussi, accessoirement, que plusieurs fonctions sont encore peu documentées dans le manuel, alors qu'elles sont peut-être utiles à connaître. Je me demande aussi, comme ça, si dans le contexte de Snow, plusieurs des fonctions non-standard présentement offertes par Gambit n'y aurait pas été déplacées, si Snow avait existé avant que ces fonctions soit implantées, et si oui, si la chose est réparable. Au sujet de Snow, j'ai été surpris, et quelque peu décu, par le manque de documentation que j'ai cru y voir, en moyenne, sur les modules contribués. À moins que je n'aie pas su regarder correctement? Il y a quand même là, pour moi, plusieurs choses avec lesquelles j'ai une familiarité à développer.

À quel point est-il pensable de récupérer la vectorisation et la versatilité de R pour Gambit? Et avec une pensée bien plus agressive et hors de proportion (ok, d'accord, un fantasme difficilement publiable), à quel point serait-il possible de recentrer l'interprète de R en direction de Gambit? Cette idée serait sans doute mal reçue chez au moins quelques-uns des développeurs actuels de R (certains ont un caractère très difficile), mais ça n'est peut-être pas inutile d'y réfléchir malgré tout.

En bref, je sens qu'il reste encore beaucoup de travail à faire, et d'idées à poursuivre. Une bonne partie n'exige que de la patience et de l'humilité, alors qu'une autre partie contient des défis d'envergure. Mais dans l'ensemble, c'est trop gros pour espérer accomplir quelque chose, simplement en volant quelques heures aux loisirs, par ci, par là. Alors, je me sens comme un peu comme tiraillé et bizarre, attiré par une flamme inaccessible ☺.

3 Snow, etc.

A long while ago, Marc Feeley suggested that we meet for discussing the contents of the Python standard library, in the context of sketching a set of good ideas to steal and push within the Snow project.

#D'où quelques inventaires préparatoires:

#- Snow index, within Snow #- SRFI index, within SRFIs #- Python library contents

J'ai commencé à regarder Snow, un peu dans le but de préparer cette rencontre avec Marc que nous nous étions promise, à l'effet de parcourir la bibliothèque qui accompagne Python, à la recherche d'inspiration et d'autres idées.

Par divers détours intellectuels, cela m'a ramené un peu à Guile, Emacs, mais plus particulièrement à Gambit. Visiblement, Gambit a fait un bon bout de chemin depuis que je l'avais sérieusement visité.

Depuis plusieurs années, j'ai passé beaucoup de temps dans Python, et un bon bout dans R aussi. Au-delà des questions de syntaxe, Python et R sont semblables à Scheme de bien des manières. Ces trois langages se ressemblent beaucoup, dans ma perception du moins. Je les trouve complémentaires, les faiblesses de l'un trouvent des solutions dans les forces de l'autre, et j'imagine qu'une pollinisation croisée serait avantageuse pour tous.

4 Versus Python

Python, au moment où je l'ai choisi, avec une simplicité comparable à celle de Scheme, mais une élégance différente au niveau de la surface. Python, au niveau de l'écriture, m'a d'abord semblé moins élégant que Scheme (mais je me suis habitué rapidement à Python par la suite). C'est la richesse de la bibliothèque de Python qui avait alors fait toute la différence pour me convaincre.

Dans mon projet MoSTex, j'utilisais abondamment Gambit, profitant de son interface C vers mes propres outils linguistiques. J'avais quand même affronté l'effort d'écrire de bons bouts en Scheme qui, en Python, étaient fournis en bibliothèque. Comme j'ai écrit MoSTex sous une forte pression, pour rencontrer mes échéances, l'épuisement avait été plus grand qu'il n'aurait été normalement nécessaire. Plus tard, une fois la poussière retombée, j'ai exploré de près l'idée de récrire MoSTex en Python, ce qui est très faisable, mais jamais avec l'élégance et la compacité que Scheme me permettait. Je ne suis parfaitement satisfait d'aucun côté.

D'autres projets qui m'ont fait particulièrement réfléchir ont été Topy et Pynits, tous deux écrits en Python. Dans les deux cas, le coeur des outils transformait des arbres, et de mon expérience avec MoSTex, je savais que Scheme aurait été particulièrement bien adapté pour ces tâches de récriture. Mais pour le reste, les bibliothèques de Scheme auraient été pauvres.

  • Pour Topy: j'avais des centaines de programmes écrits en Milou (un langage maison que tu ne connais pas) à convertir en Python, et j'ai fait le convertisseur Topy principalement dans ce but. En bout du compte, ce programme n'a pas vraiment été utile, puisque suite à un choix administratif, le système utilisant Milou a été remplacé, plus que récrit.
  • Pour Pynits: j'ai plus tard eu à travailler longtemps dans un énorme programme Python, mais écrit dans un style de surface (convention de codage) plutôt abominable selon mes propres caprices, que j'ai voulu réparer. Mais j'ai rapidement compris que ça me prendrait un temps infini dans un éditeur, même excellent. Alors j'ai écrit Pynits, conduit interactivement de l'intérieur de Vim, qui digérait et recrachait des fragments de sources.

En cours de route, Python a perdu sa simplicité, par le fait que son auteur, pour diverses raisons, a augmenté le langage d'un bon nombre de nouveautés, souvent empruntées ailleurs (dont Java, semble-t-il). Pour moi, la comparaison fait briller Scheme un peu plus, maintenant que Python a pris du ventre. Il n'en reste pas moins que Python a de bonnes bibliothèques, une orientation objet intéressante et flexible à souhait (quoique vraiment compliquée, dans le fond des détails), et aussi que l'usage s'est établi d'utiliser Python en tant que langage charnière ou d'extension dans de nombreux logiciels.

Une qualité tout-à-fait remarquable de Python est une gestion propre de ses namespaces. J'ai aussi le goût de souligner que les implanteurs de Python ont fait des efforts héroïques pour gagner de la vitesse ça et là (tiens, je pense aux techniques de consultation des dictionnaires d'attributs, et aux routines de tri), et que certains détails de l'implantation de Python vaudraient la peine d'être volés!

[2008-02-29 ven] Attending a Blitzweekend near Montreal, I gave myself a little challenge at handling Python ASTs in Scheme.

5 Versus R

R est vraiment un langage étrange. Il respire la poussière et semble vieillot de bien des manières, mais il s'y trouve quand même plusieurs réussites remarquables. Me viennent spontanément à l'esprit: la vitesse, la documentation interne et externe, l'interface vers les autres langages et, bien sûr, l'abondance et la richesse des bibliothèques.

En R, pour utiliser la terminologie de Gambit, il y a des vecteurs homogènes partout, les procédures ou fonctions du système (et même celles des usagers) savent les traiter en vrac, ce qui fait que les calculs sont vectorisés très souvent. Sur une machine non-vectorielle, le fait que les boucles vectorisées sont implantées en C, font qu'elles sont quand même bien efficaces. Contrairement à Gambit, les vecteurs homogènes sont exploitables sans devoir actualiser les objets individuels intermédiaires. Dans la culture du langage, on apprend à penser les algorithmes même élémentaires en traitements vectoriels, et ces subtilités d'écriture deviennent familières avec le temps — quoique, à mon avis, les écritures souvent très compactes qui en résultent sont des concentrés de subtilité parfois difficiles à lire.

Les délais d'évaluation (la fabrication de promesses) sont présents partout, et automatiques, principalement lors du passage des arguments d'une fonction. Un effet accessoire intéressant est qu'il est toujours possible à une fonction d'accéder à l'arbre représentatif de l'évaluation de son argument avant qu'il ne soit évalué pour de bon, et de pouvoir ainsi en fabriquer une représentation décompilée. Ainsi, une routine qui trace un graphique peut facilement titrer les variables ou l'expression, sans qu'il soit nécessaire à l'utilisateur de cette routine de les expliciter. Par ailleurs, la copie d'un vecteur homogène est retardée jusqu'au moment de sa première modification, qui a souvent lieu dans une routine ayant reçu ce vecteur copié en paramètre, il en résulte souvent une économie considérable dans l'usage de la mémoire, et des astuces dans ce coin allègent le travail du ramasseur de miettes.

Les vecteurs homogènes ont des attributs optionnels, mais généralement utilisés, dont l'information de dimensions (lorsque le vecteur représente une matrice ou super-matrice), le nom des dimensions, et le nom des éléments le long de chaque dimension (ou le long du vecteur s'il n'a pas de dimension). Cette information est préservée et transmise lors des calculs, ce qui fait qu'en bout du compte, au moment des impressions ou de diagnostics, l'usager dispose d'une information exprimée dans les termes qu'il a choisis, ce qui est remarquablement utile.

Snow m'a semblé un enfant pauvre au niveau de la documentation structurelle (obligatoire ou quasi-obligatoire), un peu comme pour Scheme. Python est mieux placé à ce sujet, un peu aligné dans la direction de Emacs, mais probablement à peu près au niveau de Java. Emacs est nettement meilleur. R me semble vraiment remarquable par comparaison, et j'ai eu l'impression (peut-être non fondée?) que le devis de Snow aurait été possiblement différent, si R avait été examiné d'abord. Il a sûrement fallu beaucoup de courage et de constance pour établir, dans R, une telle discipline, qui fait maintenant partie de la culture, et que personne parmi les contributeurs oserait ne pas suivre.

Le passage des arguments aux fonctions est plus compliqué, astucieux (mais utile) en R qu'en Python, et en Python qu'en Scheme, en autant que je sache. Mais il s'y trouve aussi quelques inélégances. C'est un problème important, parce que l'appel d'une fonction est une opération tellement fondamentale, mais l'équilibre correct entre la vitesse et la flexibilité est un problème très délicat.

Python et Gambit, à ma connaissance, sont limités à C (et à eux-mêmes) comme langages d'implantation et d'extension. R est écrit dans son propre langage, mais aussi en C, en C++ et en FORTRAN. De plus, des interfaces optionnels existent pour Java, Perl, Python, et quelques autres aussi. Un grand nombre de bibliothèques ou formats externes populaires (ODBC, MySQL et les autres, les formats d'images, GTK, Tcl/Tk, Cairo, XML, Excel, etc.) sont disponibles. Autrement dit, il démontre une étonnante ouverture. L'installation de tous les paquetages est d'une aisance comparable à celle Snowman, mais on sent dans ce domaine une maturité indéniablement plus grande.

Par contre, R souffre horriblement (à mon avis) du manque de namespaces. Oh, il y a bien une implantation des namespaces pour R, de même qu'il y a aussi deux orientations objets officielles, et plusieurs autres orientations objets optionnelles. Mais en général, il semble que l'usage de ces outils (un peu moins la première orientation objet officielle) ralentit considérablement le système. Certains usagers disent aussi qu'un cerveau humain n'a pas assez de neurones pour comprendre comment ça marche! Ce qui fait qu'en pratique, ils semblent assez peu utilisés.

La foison des bibliothèques n'allège pas le problème des collisions de noms, et les gens réagissent en dénaturant l'orthographe de mille et une manières, ce qui devient extrêmement exigeant pour la mémoire des utilisateurs, qui doit retenir la relation entre l'orthographe d'une fonction, et son implantation particulière. De plus, la difficulté de respecter tous les standards de publication d'une bibliothèque (c'est mon hypothèse) fait en sorte que chacune est un peu surchargée de routines utilitaires qui deviennent ensuite populaires. Cette fois-ci, la mémoire de l'utilisateur est sollicitée pour se souvenir que telle fonction utilitaire se trouve dans telle bibliothèque, bibliothèque dont le but et le nom n'ont rien à voir avec la fonction en question.

Une autre chose, et c'est là que je rêve à Gambit parfois, c'est que l'interprète R est lent, et que parmi les développeurs, l'espoir de le compiler un jour est très lointain. La vitesse étonnante de R provient de ses bibliothèques en C et en FORTRAN, et l'usage de la vectorisation primitive. Mais certains algorithmes sont scalaires par nature, et difficilement vectorisables, et j'ai l'impression que les contributeurs fabriqueraient des extensions C ou C++ moins souvent, si l'interprète était plus performant en lui-même. Une partie bien visible des communications des usagers sur des sujets non strictement scientifiques, dans les forums de discussion du langage, sont relatives à des débordements de temps ou de mémoire, et sur le partage conséquent d'astuces de vectorisation, pour éviter ces débordements. Il me semble confusément que si R avait était basé sur un Scheme efficace, plutôt que sur un Scheme maison, l'équilibre des choses aurait été bien différent.

6 Opinions

[2002-01-22 mar] Many people consider Scheme has being a toy, and not any Lisp. In my correspondence with various people, I observed that this lack of praise is recurrent from people who like Common Lisp. I would expect that PL/I people despise Pascal in similar ways, for similar reasons. I do not take offence of remarks like the above, and you should not either. These only represent cultural differences, and I'm sure no harm was ever intended.

For one, I am attracted to simplicity, and this is why I loved Pascal in its time, and have been very happy with Scheme before discovering Python. In my youth, I used Lisp a lot, and contributed Lisp interpreters, compilers and loaders. I also did my PL/I duties very carefully. In a word, I tasted complexity, my love for simplicity is not a purely intellectual exercise. :-)

I made a few big applications with Gambit: a full Scheme implementation with nice and usable system interfaces for extensions. It also offers an optimising compiler producing C, which you can then turn into machine code. I got CPU intensive, difficult applications to fly at reasonable speed.

We should not be overly snob or fussy: it's incredible all the good work you can do with toys :-), when these are well designed and implemented!