Scheme vs Common Lisp: Quelles caractéristiques ont fait la différence dans votre projet? [fermé]


155

Les questions vagues «Scheme vs Common Lisp» ne manquent pas à la fois sur StackOverflow et sur ce site. Je souhaite donc que celui-ci soit plus ciblé. La question s'adresse aux personnes qui ont codé dans les deux langues:

Lors du codage dans Scheme, quels éléments spécifiques de votre expérience de codage Common Lisp avez-vous le plus oublié? Ou, inversement, en codant en Common Lisp, qu'avez-vous oublié de coder en Scheme?

Je ne parle pas nécessairement uniquement de fonctionnalités linguistiques. Ce qui suit sont toutes des choses valables à manquer, en ce qui concerne la question:

  • Bibliothèques spécifiques.
  • Caractéristiques spécifiques des environnements de développement tels que SLIME, DrRacket, etc.
  • Fonctions d'implémentations particulières, telles que la capacité de Gambit à écrire des blocs de code C directement dans votre source Scheme.
  • Et bien sûr, les fonctionnalités linguistiques.

Exemples du type de réponses que j'espère:

  • "J'essayais d'implémenter X dans Common Lisp, et si j'avais les suites de première classe de Scheme, j'aurais totalement fait Y, mais je devais plutôt faire Z, ce qui était plus pénible."
  • "La création de scripts pour le processus de construction de mon projet Scheme devenait de plus en plus pénible à mesure que mon arbre source grandissait et que je reliais de plus en plus de bibliothèques C. Pour mon prochain projet, je suis revenu à Common Lisp."
  • "J'ai une grande base de code C ++ existante, et pour moi, pouvoir intégrer des appels C ++ directement dans mon code Gambit Scheme valait totalement les défauts que Scheme peut avoir par rapport à Common Lisp, même en l'absence de prise en charge de SWIG."

J'espère donc des récits de guerre plutôt que des sentiments généraux tels que "Le régime est un langage plus simple", etc.


25
Une excellente question bien formulée. Je suis curieux à ce sujet moi-même; J'espère que certaines personnes possédant une expertise dans les deux langues sont disposées à fournir des informations.
Robert Harvey le

1
@Josh K - il est clairement redevable, mais il n'y a pas nécessairement une seule réponse définitive. Sauf que je parie qu'il y en aura un parce que quelqu'un donnera une réponse tellement géniale que tout le monde est comme un whoa!
Glenatron

4
@Josh: Alors peut-être que vous n'êtes pas familier avec Scheme et Common Lisp. Les deux langues sont très puissantes en elles-mêmes, mais ni l'une ni l'autre ne sont acceptées par la majorité. Pourquoi est-ce? C'est peut-être parce qu'il y a beaucoup de dialectes; lequel choisis-tu? Une comparaison de ce type pourrait être très éclairante, et le PO a soigneusement formulé la question afin de limiter le champ d'application à des réponses qui, à mon avis, sont très spécifiques et susceptibles de réponse.
Robert Harvey le

13
Les gens, ne fermez pas la question simplement parce que vous ne l'aimez pas ou ne pouvez pas vous rapporter à elle. C'est clairement une "vraie" question; si vous ne pouvez pas trouver une meilleure raison de le fermer, vous ne devriez pas voter pour le fermer.
Robert Harvey le

4
Vous pouvez envoyer un courriel à Richard Stallman pour obtenir sa réponse.
Wassimans

Réponses:


100

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.


1
Wow, cela a dû être un code Delphi vraiment horrible s'il a réussi à exécuter 3-6x plus lentement qu'une implémentation Lisp! :(
Mason Wheeler

2
+1: La chose la plus intéressante à propos de cet article est le fait que vous êtes passé de Lisp à Scheme après avoir réalisé un projet majeur à Lisp. (Ou peut-être que je me cache depuis trop longtemps sur comp.lang.lisp.)
Larry Coleman

25
"Wow, ça doit être du code Delphi vraiment horrible s'il a réussi à exécuter 3-6x plus lentement qu'une implémentation Lisp!" D'accord, je considérerai cela comme un échec pour ne pas l'expliquer mieux. L'implémentation Lisp a été en mesure de transformer les expressions utilisateur en expressions Lisp - un processus trivialement facile - puis de compiler les expressions Lisp en code natif (avec optimisation complète). C'est le sens de la dixième règle de Greenspun.
Michael Lenaghan

1
Réponse fantastique! Je le choisirai, du moins jusqu’à ce qu’un meilleur apparaisse :) Une question: vous dites que vous avez décidé d’utiliser Chez Scheme en fonction de l’état du terrain "il y a longtemps". Pourriez-vous préciser une année?
SuperElectric

11
Ce point, que l'implémentation de LISP est libre de compiler quelque chose jusqu'au code machine, plutôt que de compter sur un interprète, est subtil et très utile. Le livre "Let Over Lambda" souligne que c'est précisément la raison pour laquelle le paquet portable Common LISP regexp, qui clone la syntaxe PERL regexp, surpasse PERL de manière significative. PERL, au bas de la hiérarchie, dispose d’un interprète d’expression rationnelle. Le paquet Common LISP compile les expressions rationnelles en code.
John R. Strohm le

37

Habituellement, je n'aime pas coller un lien comme réponse, mais j'ai écrit un article sur ce blog. Ce n'est pas exhaustif, mais il passe en revue certains des principaux points.

http://symbo1ics.com/blog/?p=729

Edit : Voici les principaux points:

  1. EXISTENCE : Les deux lisps sont venus après un groupe d'autres lisps. Scheme a pris la voie minimale et axiomatique. CL a pris la route baroque.
  2. CASE : Typiquement Scheme est sensible à la casse. CL n'est pas (bien que cela puisse être). Cela manque parfois, mais son aspect pratique est débattu (par moi).
  3. NOMS : Les noms de symboles en CL sont souvent impairs et déroutants. TERPRI, PROGNetc. Scheme a généralement des noms très judicieux. C'est quelque chose qui manque dans CL.
  4. FONCTIONS : CL a un espace de noms de fonction séparé. Ce n'est pas manquer dans Scheme. Avoir un seul espace de noms permet généralement une programmation fonctionnelle très propre, ce qui est souvent difficile ou difficile dans CL. Mais cela a un coût - vous devez parfois masquer des noms tels que " list" à " lst" dans Scheme.
  5. MACROS : Les macros sales de bas niveau me manquent le plus dans Scheme. Ouais, syntax-rulestout va bien jusqu'à ce que vous vouliez vraiment pirater certaines choses. D'autre part, les macros hygiéniques sont parfois omises dans CL. N'ayant aucun moyen standard de les faire, cela signifie réinventer la roue.
  6. PORTABILITÉ : CL est souvent plus portable, même si les deux langues sont normalisées. CL est plus grand et, par conséquent, il y a plus de fonctionnalités standard à utiliser sans bibliothèques externes. Cela signifie également que davantage de choses dépendant de la mise en œuvre peuvent être faites de manière portable. En outre, Scheme souffre d’un billion d’implémentations, dont la plupart sont quelque peu incompatibles. Cela rend CL très souhaitable.
  7. BIBLIOTHÈQUES : Très lié à mon dernier point. Scheme a des SRFI mais ne sont pas universellement reconnus. Il n'y a pas de moyen portable de travailler avec des bibliothèques. CL en revanche a des moyens. Et Quicklisp est un cadeau de Dieu (Xach) - une sorte de référentiel de bibliothèques à utiliser.
  8. MISE EN ŒUVRE : Scheme souffre d'avoir autant de mises en œuvre. Il n'y a pas de réelle implémentation canonique. CL, d’autre part, a de très belles implémentations hautes performances ou à usage spécifique (hautes performances: SBCL, commerciales: Allegro, embarquées: ECL, portables: CLISP, Java: ABCL, ...).

Bien que je n’ai parlé qu’à la première personne un peu au-dessus, il devrait être clair ce qui me manque et ce qui ne me manque pas.

[Je m'excuse si elles sont trop générales. Il semble que vous souhaitiez beaucoup plus de détails spécifiques. Il y a quelques détails dans le post.]


Qu'en est-il d'un résumé (vraiment) court teaser? ^^
Dave O.

2
S'il vous plaît inline les faits saillants. Les réponses doivent être autonomes.

1
@ Dave O. et @ Thorbjørn Ravn Andersen: ajout d'un résumé à la demande. Merci.
Quadrescence

2
"La route baroque"! Quelle excellente façon de le dire.
Mark C

Common Lisp respecte la casse, mais convertit son entrée en majuscule avant de l'évaluer. Vous pouvez obtenir des lettres minuscules dans les symboles en les citant. La question de nom est parce que Scheme s'est débarrassé des mauvais vieux noms et non de CL.
David Thornley

25

J'ai récemment démarré un projet personnel en utilisant une bibliothèque avec une version C et une version Java. Je voulais utiliser Lisp pour le projet et j'ai passé environ un mois entre Common Lisp, Scheme et Clojure. J'ai de l'expérience avec les trois projets, mais uniquement avec des projets de jouets. Je vais vous parler un peu de mon expérience avec chacun d’eux avant de vous dire laquelle j’ai finalement choisi.

PLT Racket a un bon IDE qui vous permet non seulement d’évaluer les expressions à partir de l’éditeur, mais également de taper des crochets au lieu de parenthèses, en les basculant à l’endroit approprié. Racket dispose également d’un grand nombre de bibliothèques avec l’installation et d’autres encore disponibles au téléchargement. Le débogueur visuel est également utile.

SMLL (Common Lisp implémentation) n’a pas d’EDI, mais il est habituel avec les implémentations CL à source ouverte d’utiliser Emacs et SLIME. Cette combinaison peut être très efficace. Outre la possibilité d'évaluer les expressions au fur et à mesure que vous les tapez dans le fichier source, il existe également un REPL qui contient toutes les commandes d'édition d'emacs, de sorte que la copie de code peut fonctionner efficacement dans les deux sens. Même les objets affichés dans le tampon REPL peuvent être copiés et collés. Alt+(et Alt+)sont efficaces pour traiter les parenthèses et l'indentation appariées.

Toutes les fonctionnalités d'Emacs ci-dessus sont également disponibles pour Clojure. Mon expérience de montage avec Clojure est similaire à celle de Lisp. L'interopérabilité Java a bien fonctionné et j'aimerais bien faire un projet Clojure une fois qu'il sera mûr.

J'ai pu accéder à la bibliothèque en utilisant les trois (Common Lisp, Racket et Clojure), mais j'ai finalement choisi Common Lisp pour le projet. Le facteur décisif était que le FFI était beaucoup plus facile à utiliser dans Common Lisp. Le CFFI a un très bon manuel avec un exemple de code et des explications détaillées sur chaque méthode. J'ai été en mesure d'envelopper 20 fonctions C dans un après-midi et je n'ai pas eu à toucher au code depuis.

L'autre facteur était que je connaissais mieux Common Lisp que Clojure ou R6RS Scheme. J'ai lu la plupart des livres de Practical Common Lisp et Graham et je suis à l'aise avec Hyperspec. Ce n'est pas encore très codé, mais je suis sûr que cela va changer à mesure que je gagne en expérience.


Merci pour le détail! Si je vous ai bien compris, vous pensiez que le FFI de SBCL était plus facile à utiliser que celui de Clojure? Si tel est le cas, cela me surprendrait beaucoup, car vous pouvez simplement appeler des méthodes Java directement à partir de Clojure sans avoir à les envelopper. (Ou avez-vous également besoin d'appeler du code natif?)
SuperElectric, le

6
@SuperElectric: L'appel de méthodes Java "intégrées" à partir de Clojure est trivial; appeler des méthodes Java qui se trouvent dans une bibliothèque téléchargée: pas vraiment. J'ai vraiment passé plus de temps à définir correctement le chemin d'accès aux classes et les lignes d'importation qu'il ne m'a fallu pour que ma première méthode C fonctionne de SBCL avec CFFI. Mais je ne suis pas un expert de Java, alors votre kilométrage peut varier.
Larry Coleman

21

Je programme en CL et en raquette.

Je développe actuellement un site Web dans Common Lisp et j'ai écrit une série de programmes internes pour mon ancien employeur de Racket.

Pour le code interne, j'ai choisi Racket (à l'époque appelé PLT Scheme) car l'employeur était un magasin Windows et je ne pouvais pas le faire payer pour LispWorks. La seule bonne implémentation CL open-source pour Windows était (et est toujours) CCL, ce qui nécessite la prise en charge de SSE par le processeur. L'employeur, étant bon marché, utilisait du matériel de l'âge de pierre. Même si l'employeur disposait d'un matériel de qualité, la seule bibliothèque d'interface graphique importante de Common Lisp est McCLIM, qui ne fonctionne que sous Unix. Racket possède une bonne bibliothèque d’interface graphique qui fonctionne à la fois sous Unix et Windows, ce qui était essentiel au succès de mon projet.

J'ai passé plus d'un an à supporter l'éditeur primitif DrRacket. EMACS n'a pas pu transformer la version graphique de Racket, connue à l'époque sous le nom de MrEd, en inferior-lisp sous Windows. Je devais faire sans pouvoir évaluer l'expression au niveau du curseur avec une seule frappe. Au lieu de cela, je devais sélectionner manuellement l'expression S, la copier, cliquer sur la fenêtre REPL (car il n'y avait aucune frappe sur laquelle basculer), puis coller l'expression S. Je devais aussi me passer d'un éditeur capable de me montrer les arguments attendus de la fonction ou de la macro que j'utilisais. DrRacket ne remplace pas SLIME.

L'employeur utilisait une base de données propriétaire avec une API XML complexe qui nécessitait des charges d'informations apparemment inutiles pour pouvoir répondre à sa version d'une requête SELECT. J'ai décidé d'utiliser HTMLPrag à la fois pour émettre du XML vers cette API et pour analyser les réponses. Cela a très bien fonctionné.

J'ai dû apprendre le système de macros "casse de syntaxe" surchargé de Racket afin d'écrire une macro qui me permettrait d'interagir avec l'API XML très compliquée en tapant des formulaires ressemblant à SQL. Cette partie aurait été beaucoup plus facile si j'avais DEFMACRO à ma disposition. Cependant, le résultat final était toujours sans faille même s'il a fallu déployer davantage d'efforts.

De plus, je devais me passer de la macro LOOP de Common Lisp. Racket a commencé à fournir une alternative seulement après que j'ai écrit la plupart du code, et l'alternative est toujours nul par rapport à LOOP (même si l'équipe de développement de Racket insiste sur le fait que c'est mieux - ils se trompent tout simplement). J'ai fini par écrire beaucoup de formulaires LET nommés qui utilisaient "car" et "cdr" pour parcourir les listes.

En parlant de voiture et cdr, rien n’est plus frustrant que l’interprétation de (voiture '()) de Scheme comme étant une erreur. J'ai profité de la sensibilité à la casse de Racket pour implémenter CAR et CDR, qui ont la sémantique de Common Lisp. Cependant, la séparation de '() et #f rend beaucoup moins utile de renvoyer' () comme valeur par défaut.

J'ai également fini par ré-implémenter UNWIND-PROTECT et j'ai inventé mon propre système de redémarrage pour combler le vide laissé par Racket. La communauté Racket doit savoir que les redémarrages sont très utiles et faciles à mettre en œuvre.

La forme let-values ​​de Racket était trop verbeuse, j'ai donc implémenté MULTIPLE-VALUE-BIND. Cela était absolument nécessaire, car Racket exige que vous receviez toutes les valeurs générées, que vous les utilisiez ou non.

Plus tard, j’ai tenté d’écrire un client API XML eBay dans Common Lisp, mais j’ai constaté qu’il n’avait rien de tel que HTMLPrag. HTMLPrag est utile. J'ai fini par faire ce projet dans Racket. J’ai expérimenté les fonctionnalités de programmation alphabète de Racket, pour découvrir que je suis le seul programmeur sur Terre à trouver le code littéral écrit correctement plus difficile à modifier que le code ordinaire ou le code alphabétique "commentaires excessifs" mal écrit.

Mon nouveau projet est réalisé à Common Lisp, ce qui était le bon choix car la communauté Racket ne croit tout simplement pas au parallélisme, ce qui est essentiel pour ce projet. La seule chose que je pensais avoir peut-être manqué de Racket, ce sont les poursuites. Cependant, j'ai pu faire ce dont j'avais besoin en utilisant des redémarrages et, rétrospectivement, j'aurais probablement pu le faire avec une simple fermeture.


2
Je n'ai pas essayé moi-même, mais j'ai vu des articles de blog de personnes utilisant le programme de raquette en ligne de commande avec Emacs. Par exemple: bc.tech.coop/scheme/scheme-emacs.htm
Larry Coleman

5
En toute justice, on dirait que vous êtes venu à Scheme pour écrire CL au lieu d’essayer d’aborder les choses à partir d’un POV idiomatique. Par exemple, le système n'encourage-t-il pas la récidive plutôt que l'utilisation de boucles?
Traîneau

@ArtB Scheme ne se contente pas d' encourager récursion, il faut , donc de bien entendu le projet mentionné ci - dessus utilisé beaucoup de récursivité. Et cela ne servait qu'à ajouter de la répétition (vous devez inclure une copie de l'appel récursif dans chaque branche d'un condformulaire, par exemple) et des bugs (est-ce que j'ai écrit le test de terminaison de boucle correctement à cette époque?) Même aujourd'hui, j'ai l'impression Cette raquette est principalement destinée aux étudiants et non aux programmeurs professionnels. Chaque fois que j'entends parler de quelqu'un d'autre que moi qui l'utilise, ils utilisent la sous-langue "Étudiant débutant" et c'est pour une classe.
Jeter le compte compte

Si vous répétez du code sur des COND, dites-vous que vous avez simplement besoin d'une autre fonction?
Traîneau le

@ArtB Une fonction pour appeler la fonction de boucle avec des arguments différents? Ce serait un peu inutile. Vous voyez ce genre de répétition dans à peu près n'importe quel code Scheme. Il y a même des exemples dans le code source de Racket.
Compte Jeté

5

Scheme est conçu avec une compilation séparée à l'esprit. En conséquence, la puissance de ses macros est souvent limitée de manière sévère, même avec les extensions qui permettent un defmacro de type Common Lisp au lieu d’un système de macro médiocre, limitant l’hygiène. Il n'est pas toujours possible de définir une macro définissant une autre macro destinée à une utilisation immédiate dans une ligne de code suivante. Et une telle possibilité est essentielle pour la mise en œuvre de compilateurs eDSL efficaces.

Il va sans dire que les implémentations Scheme avec uniquement des macros hygiéniques R5RS me sont à peine utiles, car mon style de métaprogrammation ne peut être traduit de manière adéquate en hygiène.

Heureusement, certaines implémentations de Scheme (par exemple, Racket) ne sont pas soumises à cette limitation.


1
Bonjour, je viens juste de commencer à me familiariser avec Scheme en utilisant Racket. Souhaitez-vous donner un exemple rapide d'utilisation de macros non hygiéniques dans Racket? Le type de macros disponibles semble être l’un des points les plus controversés entre CL et Scheme.
orange80

@ orange80, la première approche consiste à utiliser docs.racket-lang.org/mzlib/mzlib_defmacro.html Et, bien sûr, en mode R6RS, il existe un moyen moins restrictif.
SK-logic

@ SK-logic que faites-vous avec des macros si peu hygiéniques?
Traîneau

1
@ArtB, j'implémente les eDSL en tant que fonctions de compilateur qui peuvent faire beaucoup avec leur source AST. L’hygiène est une nuisance totale dans le cadre d’une telle approche. Vous pouvez voir comment cela fonctionne: github.com/combinatorylogic/mbase
SK-logic le
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.