Mon diplôme de premier cycle était en sciences cognitives et intelligence artificielle. A partir de là, j'ai eu une introduction à Lisp à un cours. Je pensais que le langage était intéressant (comme dans "élégant") mais je n'y ai pas vraiment réfléchi avant de tomber sur la Dixième Règle de Greenspun beaucoup plus tard:
Tout programme C ou Fortran suffisamment compliqué contient une implémentation lente ad hoc, spécifiée de manière informelle, corrigée de bogues, de la moitié de Common Lisp.
L'argument de Greenspun était (en partie) que de nombreux programmes complexes ont des interprètes intégrés. Plutôt que de construire un interprète dans un langage, il a suggéré qu'il serait plus logique d'utiliser un langage comme Lisp qui possède déjà un interpréteur (ou un compilateur) intégré.
À l'époque, je travaillais sur une application assez grosse qui effectuait des calculs définis par l'utilisateur à l'aide d'un interpréteur personnalisé pour une langue personnalisée. J'ai décidé d'essayer de réécrire son noyau dans Lisp sous la forme d'une expérience à grande échelle.
Cela a pris environ six semaines. Le code original était d'environ 100 000 lignes de Delphi (une variante de Pascal). En Lisp, cela a été réduit à environ 10 000 lignes. Encore plus surprenant, le moteur Lisp était 3-6 fois plus rapide. Et gardez à l’esprit que c’était le travail d’un néophyte Lisp! Toute cette expérience m'a vraiment ouvert les yeux. pour la première fois, j'ai vu la possibilité de combiner performance et expressivité dans une seule langue.
Quelque temps plus tard, lorsque j'ai commencé à travailler sur un projet Web, j'ai auditionné un certain nombre de langues. J'ai inclus Lisp et Scheme dans le mix. En fin de compte, j'ai sélectionné un schéma d'implémentation - Chez Scheme . Je suis très content des résultats.
Le projet Web est un "moteur de sélection" hautes performances . Nous utilisons Scheme de différentes manières, du traitement des données à leur interrogation en passant par la génération de pages. Dans de nombreux endroits, nous avons commencé avec une langue différente, puis avons migré vers Scheme pour des raisons que je vais décrire brièvement ci-dessous.
Maintenant, je peux répondre à votre question (au moins en partie).
Au cours de l'audition, nous avons examiné diverses applications de Lisp et Scheme. Du côté de Lisp, nous avons examiné (je crois) Allegro CL, CMUCL, SBCL et LispWorks. Du côté Scheme, nous avons examiné (je crois) Bigloo, Chicken, Chez, Gambit. (Le choix de la langue a été fait il y a longtemps; c'est pourquoi je suis un peu confus. Je peux extraire quelques notes si c'est important.)
Dès le départ, nous recherchions a) des threads natifs et b) un support Linux, Mac et Windows. Ces deux conditions combinées ont frappé tout le monde mais (je pense) Allegro et Chez out - donc, pour poursuivre l'évaluation, nous avons dû assouplir l'exigence du multi-threading.
Nous avons mis au point une série de petits programmes que nous avons utilisés pour l’évaluation et les tests. Cela a révélé un certain nombre de problèmes. Par exemple: certaines implémentations présentaient des défauts qui empêchaient certains tests de s’achever; certaines implémentations ne pouvaient pas compiler le code au moment de l'exécution; certaines implémentations ne pouvaient pas facilement intégrer du code compilé à l'exécution avec du code précompilé; certaines applications avaient des éboueurs nettement meilleurs (ou nettement pires) que les autres; etc.
Pour nos besoins, seules les trois implémentations commerciales - Allegro, Chez et Lispworks - ont réussi nos tests primaires. Des trois, seul Chez a réussi tous les tests avec brio. À l’époque, je pense que Lispworks n’avait pas de threads natifs sur aucune plate-forme (je pense qu’ils l’avaient maintenant) et je pense qu’Allegro n’avait que des threads natifs sur certaines plates-formes. De plus, Allegro avait des droits de licence d’exécution «appelez-nous» que je n’aimais pas beaucoup. Je crois que Lispworks n’avait aucuns frais d’exécution et Chez avait un arrangement simple (et très raisonnable) (et il ne s’engage que si vous avez utilisé le compilateur au moment de l’exécution).
Après avoir produit des morceaux de code assez significatifs dans Lisp et Scheme, voici quelques points de comparaison et de contraste:
Les environnements Lisp sont beaucoup plus matures. Vous en avez plus pour votre argent. (Ceci dit, plus de code équivaut aussi à plus de bugs.)
Les environnements Lisp sont beaucoup plus difficiles à apprendre. Vous avez besoin de beaucoup plus de temps pour devenir compétent; Common Lisp est un langage énorme - et c'est avant que vous ne trouviez les bibliothèques ajoutées aux implémentations commerciales. (Cela dit, le cas de la syntaxe de Scheme est bien plus subtil et compliqué que n'importe quoi en Lisp.)
Il est parfois un peu plus difficile de produire des fichiers binaires dans les environnements Lisp. Vous devez "secouer" votre image pour supprimer les bits inutiles. Si vous n'exercez pas votre programme correctement au cours de ce processus, des erreurs d'exécution risquent de se produire ultérieurement. . En revanche, avec Chez, nous compilons un fichier de niveau supérieur qui inclut tous les autres fichiers dont il a besoin et nous avons terminé.
J'ai déjà dit que nous avions utilisé Scheme dans un certain nombre d'endroits où nous n'avions pas l'intention initialement. Pourquoi? Je peux penser à trois raisons qui me viennent à l’esprit.
Premièrement, nous avons appris à faire confiance à Chez (et son développeur, Cadence). Nous avons beaucoup demandé à cet outil, qui a toujours été efficace. Par exemple, Chez a toujours eu un nombre de défauts trivial et son gestionnaire de mémoire a été très, très bon.
Deuxièmement, nous avons appris à aimer la performance de Chez. Nous utilisions quelque chose qui ressemblait à un langage de script - et nous en tirions une vitesse de code natif. Pour certaines choses qui importaient peu - mais ça ne faisait jamais mal, et parfois ça aidait énormément.
Troisièmement, nous avons appris à aimer l’abstraction que Scheme pouvait fournir. Je ne parle pas seulement de macros, au fait; Je parle de choses comme les fermetures, les lambdas, les coups de queue, etc. Une fois que vous commencez à penser en ces termes, les autres langues semblent plutôt limitées en comparaison.
Le régime est-il parfait? Non; c'est un compromis. Tout d’abord, cela permet aux développeurs individuels d’être plus efficaces - mais il est plus difficile pour les développeurs de s’enfiler dans le code de l’autre parce que les indicateurs utilisés par la plupart des langages (par exemple, les boucles for) sont manquants dans Scheme (par exemple, il existe un million de façons de le faire. une boucle for). Deuxièmement, il existe un groupe beaucoup plus restreint de développeurs à qui parler, engager, emprunter, etc.
En résumé, je dirais que Lisp et Scheme offrent des fonctionnalités qui ne sont pas disponibles partout ailleurs. Cette capacité est un compromis, elle aurait donc intérêt à être logique dans votre cas particulier. Dans notre cas, les facteurs déterminants entre le choix d'utiliser Lisp ou Scheme concernaient davantage des fonctionnalités très fondamentales (support de plate-forme, threads de plate-forme, compilation au moment de l'exécution, licences d'exécution) plutôt que des fonctionnalités de langage ou de bibliothèque. Encore une fois, dans notre cas, cela représentait également un compromis: avec Chez, nous avions les fonctionnalités essentielles que nous souhaitions, mais nous avions perdu les bibliothèques étendues des environnements Lisp commerciaux.
Aussi, juste pour répéter: nous avons examiné les différents Lisps et Schemes il y a longtemps; ils ont tous évolué et amélioré depuis.