Mein Grundstudium war Kognitionswissenschaft und Künstliche Intelligenz. Von da an hatte ich eine Ein-Gänge-Einführung in Lisp. Ich fand die Sprache interessant (wie in "elegant"), dachte aber nicht wirklich darüber nach, bis ich viel später auf Greenspuns Zehnte Regel stieß:
Jedes ausreichend komplizierte C- oder Fortran-Programm enthält eine ad-hoc, informell spezifizierte, fehlerbehaftete, langsame Implementierung der Hälfte von Common Lisp.
Greenspuns Argument war (teilweise), dass in vielen komplexen Programmen Interpreter eingebaut sind. Anstatt einen Interpreter in eine Sprache zu integrieren, schlug er vor, dass es sinnvoller sein könnte, eine Sprache wie Lisp zu verwenden, in der bereits ein Interpreter (oder Compiler) integriert ist.
Zu der Zeit arbeitete ich an einer ziemlich großen App, die benutzerdefinierte Berechnungen mit einem benutzerdefinierten Interpreter für eine benutzerdefinierte Sprache durchführte. Ich beschloss, seinen Kern in Lisp als großes Experiment neu zu schreiben.
Es dauerte ungefähr sechs Wochen. Der ursprüngliche Code war ~ 100.000 Zeilen Delphi (eine Pascal-Variante). In Lisp wurde das auf ~ 10.000 Zeilen reduziert. Noch überraschender war jedoch die Tatsache, dass die Lisp-Engine 3-6-mal schneller war. Und denken Sie daran, dass dies die Arbeit eines Lisp-Neulings war! Diese ganze Erfahrung hat mir die Augen geöffnet. Zum ersten Mal sah ich die Möglichkeit, Leistung und Ausdruckskraft in einer einzigen Sprache zu verbinden.
Einige Zeit später, als ich anfing, an einem webbasierten Projekt zu arbeiten, sprach ich eine Reihe von Sprachen vor. Ich habe Lisp und Scheme in die Mischung aufgenommen. Am Ende habe ich eine Schema-Implementierung ausgewählt - Chez-Schema . Ich bin sehr zufrieden mit dem Ergebnis.
Das webbasierte Projekt ist eine leistungsstarke "Auswahlmaschine" . Wir verwenden Scheme auf verschiedene Arten, von der Verarbeitung von Daten über die Abfrage von Daten bis zur Seitenerstellung. An vielen Stellen haben wir tatsächlich mit einer anderen Sprache begonnen, sind aber aus Gründen, die ich im Folgenden kurz beschreiben werde, zu Scheme gewechselt.
Jetzt kann ich Ihre Frage (zumindest teilweise) beantworten.
Während der Audition haben wir uns verschiedene Lisp- und Scheme-Implementierungen angesehen. Auf der Lisp-Seite haben wir uns (glaube ich) Allegro CL, CMUCL, SBCL und LispWorks angesehen. Auf der Schemaseite haben wir uns (glaube ich) Bigloo, Chicken, Chez, Gambit angesehen. (Die Sprachauswahl ist schon lange her. Deshalb bin ich ein bisschen dunstig. Ich kann ein paar Notizen ausgraben, wenn es wichtig ist.)
Von Anfang an suchten wir nach a) nativen Threads und b) Unterstützung für Linux, Mac und Windows. Diese beiden Bedingungen zusammen haben alle außer (ich denke) Allegro und Chez umgehauen. Um die Bewertung fortzusetzen, mussten wir die Multithreading-Anforderungen lockern.
Wir haben eine Reihe kleiner Programme zusammengestellt und diese für Evaluierungen und Tests verwendet. Das ergab eine Reihe von Problemen. Beispiel: Einige Implementierungen wiesen Fehler auf, die verhinderten, dass einige Tests vollständig ausgeführt werden konnten. Einige Implementierungen konnten zur Laufzeit keinen Code kompilieren. Einige Implementierungen konnten zur Laufzeit kompilierten Code nicht einfach in vorkompilierten Code integrieren. Einige Implementierungen hatten Müllsammler, die deutlich besser (oder deutlich schlechter) waren als die anderen. usw.
Für unsere Bedürfnisse haben nur die drei kommerziellen Implementierungen - Allegro, Chez und Lispworks - unsere primären Tests bestanden. Von den dreien bestand nur Chez alle Tests mit Bravour. Zu der Zeit, glaube ich, hatte Lispworks auf keiner Plattform native Threads (ich glaube, das tun sie jetzt), und ich glaube, Allegro hatte auf einigen Plattformen nur native Threads. Darüber hinaus hatte Allegro eine Laufzeitlizenzgebühr, die mir nicht sonderlich gut gefallen hat. Ich glaube, Lispworks hatte keine Laufzeitgebühr und Chez hatte eine unkomplizierte (und sehr vernünftige) Vereinbarung (und diese trat nur in Kraft, wenn Sie den Compiler zur Laufzeit verwendeten).
Hier sind einige Vergleichs- und Kontrastpunkte, die sowohl in Lisp als auch in Scheme etwas bedeutende Codestücke hervorgebracht haben:
Die Lisp-Umgebungen sind weitaus ausgereifter. Sie bekommen viel mehr fürs Geld. (Allerdings bedeutet mehr Code auch mehr Fehler.)
Die Lisp-Umgebungen sind weitaus schwieriger zu erlernen. Sie brauchen viel mehr Zeit, um kompetent zu werden. Common Lisp ist eine riesige Sprache - und das ist, bevor Sie zu den Bibliotheken kommen, die die kommerziellen Implementierungen hinzufügen. (Trotzdem ist der Syntaxfall von Scheme weitaus subtiler und komplizierter als alles, was in Lisp vorkommt.)
In den Lisp-Umgebungen kann es etwas schwieriger sein, Binärdateien zu erstellen. Sie müssen Ihr Image "schütteln", um nicht benötigte Teile zu entfernen. Wenn Sie Ihr Programm während dieses Vorgangs nicht korrekt ausführen, können später Laufzeitfehler auftreten . Im Gegensatz dazu kompilieren wir mit Chez eine Datei der obersten Ebene, die alle anderen benötigten Dateien enthält, und wir sind fertig.
Ich sagte zuvor, dass wir Scheme an einer Reihe von Orten eingesetzt haben, die wir ursprünglich nicht beabsichtigt hatten. Warum? Mir fallen drei Gründe ein.
Zuerst haben wir gelernt, Chez (und seinem Entwickler Cadence) zu vertrauen. Wir haben viel vom Tool verlangt und es lieferte konsequent. Zum Beispiel hatte Chez in der Vergangenheit nur eine geringe Anzahl von Fehlern, und sein Speichermanager war sehr, sehr gut.
Zweitens haben wir gelernt, die Leistung von Chez zu lieben. Wir haben etwas verwendet, das sich wie eine Skriptsprache anfühlte - und wir haben daraus die Geschwindigkeit des nativen Codes gewonnen. Für einige Dinge, die keine Rolle spielten - aber es tat nie weh, und manchmal half es sehr viel.
Drittens haben wir gelernt, die Abstraktion zu lieben, die das Schema bieten kann. Ich meine übrigens nicht nur Makros; Ich meine Dinge wie Verschlüsse, Lambdas, Tail-Calls usw. Sobald Sie anfangen, in diesen Begriffen zu denken, scheinen andere Sprachen im Vergleich eher begrenzt zu sein.
Ist das Schema perfekt? Nein; Es ist ein Kompromiss. Erstens können einzelne Entwickler effektiver arbeiten - für Entwickler ist es jedoch schwieriger, sich gegenseitig den Code zu entlocken, da die Wegweiser der meisten Sprachen (z. B. für Schleifen) im Schema fehlen (z. B. gibt es eine Million Möglichkeiten) eine for-Schleife). Zweitens gibt es einen viel kleineren Pool von Entwicklern, mit denen man reden, die man anheuern, ausleihen usw. kann.
Zusammenfassend würde ich sagen: Lisp und Scheme bieten einige Funktionen, die nirgendwo sonst verfügbar sind. Diese Fähigkeit ist ein Kompromiss, also sollte es in Ihrem speziellen Fall sinnvoller sein. In unserem Fall hatten die entscheidenden Faktoren für die Entscheidung für Lisp oder Scheme mehr mit sehr grundlegenden Funktionen (Plattformunterstützung, Plattformthreads, Laufzeitkompilierung, Laufzeitlizenzierung) zu tun als mit Sprach- oder Bibliotheksfunktionen. Auch in unserem Fall war dies ein Kompromiss: Mit Chez haben wir die Kernfunktionen erhalten, die wir wollten, aber wir haben die umfangreichen Bibliotheken verloren, die die kommerziellen Lisp-Umgebungen hatten.
Um es noch einmal zu wiederholen: Wir haben uns vor langer Zeit die verschiedenen Lisps und Schemata angesehen. Sie haben sich alle seitdem weiterentwickelt und verbessert.