Die Absicht meiner Frage ist nicht , einen Flammenkrieg zu beginnen, sondern zu bestimmen, unter welchen Umständen jede Sprache "das beste Werkzeug für den Job" ist.
Ich habe mehrere Bücher über Clojure gelesen ( Programmieren von Clojure , Praktisches Clojure , Die Freude an Clojure und die Manning Early Access-Ausgabe von Clojure in Aktion ), und ich denke, es ist eine fantastische Sprache. Ich lese gerade Let Over Lambda, das sich hauptsächlich mit Common Lisp-Makros befasst und auch eine sehr interessante Sprache ist.
Ich bin kein Lisp-Experte (eher ein Neuling), aber diese Sprachfamilie fasziniert mich ebenso wie die funktionale Programmierung im Allgemeinen.
Vorteile von Clojure (und Nachteile von "anderen"):
Läuft auf der JVM.
Die JVM ist eine sehr stabile, leistungsstarke Sprachumgebung, die Suns Traum vom "Einmal schreiben, [fast] überall ausführen" ziemlich gut erfüllt. Ich kann Code auf mein Macbook Pro schreiben, ihn in eine ausführbare JAR-Datei kompilieren und ihn dann unter Linux und Microsoft Windows mit wenig zusätzlichen Tests ausführen.
Die (Hotspot- und andere) JVM unterstützt eine qualitativ hochwertige Speicherbereinigung und eine sehr performante Just-in-Time-Kompilierung und -Optimierung. Wo ich vor ein paar Jahren alles geschrieben habe, was in C schnell laufen musste, zögere ich jetzt nicht, dies in Java zu tun.
Standardmodell, einfaches Multithreading-Modell. Hat Common Lisp ein Standard-Multithreading-Paket?
Bricht die Monotonie all dieser Klammern mit
[]
, auf{}
, und#{}
obwohl Common Lisp-Experten mir wahrscheinlich sagen werden, dass Sie diese mit Lesermakros zu CL hinzufügen können.
Nachteile von Clojure :
- Läuft auf der JVM.
- Keine Schwanzrekursion oder Fortsetzung. Unterstützt Common Lisp Fortsetzungen? Ich glaube, das Programm erfordert Unterstützung für beide.
Vorteile anderer (insbesondere Common Lisp) (und Nachteile von Clojure):
Benutzerdefinierte Lesermakros.
Weitere Vorteile?
Gedanken? Andere Unterschiede?
quelle
Antworten:
Meine persönliche Liste der Gründe, warum ich Clojure anderen Lisps vorziehe (ps Ich finde immer noch, dass alle Lisps großartig sind!):
Läuft auf der JVM - erhält daher automatischen Zugriff auf das fantastische Engineering in der JVM selbst (erweiterte Garbage Collection-Algorithmen, HotSpot JIT-Optimierung usw.)
Sehr gute Java-Interoperabilität - bietet Kompatibilität mit der Vielzahl von Bibliotheken im Java / JVM-Sprachökosystem. Ich habe Clojure als "Klebesprache" verwendet, um verschiedene Java-Bibliotheken mit guter Wirkung zu verbinden. Da ich auch viel Java-Code entwickle, ist es für mich hilfreich, dass Clojure gut in Java-Tools integriert ist (z. B. verwende ich Maven, Eclipse mit Plugin gegen den Uhrzeigersinn für meine Clojure-Entwicklung).
Schöne Syntax für Vektoren
[1 2 3]
, Karten{:bob 10, :jane 15}
und Mengen#{"a" "b" "c"}
- ich halte diese ziemlich wichtigen Werkzeuge für die moderne Programmierung (zusätzlich zu Listen natürlich!).Ich persönlich mag die Verwendung von eckigen Klammern zum Binden von Formularen: zB
(defn foo [a b] (+ a b))
- Ich denke, das macht das Lesen von Code etwas klarer.Der Schwerpunkt liegt auf einer verzögerten, funktionalen Programmierung mit dauerhaften, unveränderlichen Datenstrukturen. Insbesondere die gesamte Clojure-Kernbibliothek unterstützt dies standardmäßig
Hervorragende STM-Implementierung für Multi-Core-Parallelität. Ich glaube, Clojure hat momentan die beste Parallelitätsgeschichte aller Sprachen (siehe dieses Video für weitere Informationen von Rich Hickey selbst ).
Es ist ein Lisp-1 (wie Schema), das ich persönlich bevorzuge (ich denke, in einer funktionalen Sprache ist es sinnvoll, Funktionen und Daten im selben Namespace zu halten).
quelle
Beachten Sie, dass Clojure eine Sprache und eine Implementierung ist (normalerweise in der JVM). Common Lisp ist eine Sprache mit mehr als zehn verschiedenen Implementierungen. Wir haben hier also eine Kategorie-Nichtübereinstimmung. Sie können beispielsweise Clojure mit SBCL vergleichen.
Allgemein:
Eine Version von Common Lisp läuft auf der JVM: ABCL
Die meisten anderen Common Lisp-Implementierungen tun dies nicht
Die meisten CL-Implementierungen verfügen über Multitasking-Funktionen. Eine Bibliothek bietet eine gemeinsame Schnittstelle
Common Lisp hat eine Syntax für Arrays. Die Syntax für andere Datentypen kann vom Benutzer geschrieben werden und wird von verschiedenen Bibliotheken bereitgestellt.
Common Lisp unterstützt weder Tail Call-Optimierung noch Fortsetzungen. Implementierungen bieten Gesamtbetriebskosten und Bibliotheken bieten eine Form von Fortsetzung.
quelle
Ein wichtiger Unterschied zwischen Clojure und Common Lisp besteht darin, dass Clojure die funktionale Programmierung genauer beschreibt. Clojures Philosophie, Redewendungen und bis zu einem gewissen Grad Sprache / Bibliotheken ermutigen stark und bestehen manchmal darauf, dass Sie auf funktionale Weise programmieren (keine Nebenwirkungen, kein veränderlicher Zustand).
Common Lisp unterstützt definitiv die funktionale Programmierung, ermöglicht aber auch veränderbare Zustands- und Imperativprogrammierung.
Natürlich bietet die funktionale Programmierung im Bereich der Parallelität und auf andere Weise eine Reihe von Vorteilen. Wenn alles andere gleich ist, ist es auch gut, die Wahl zu haben, welchen Ansatz Sie für jede Situation verwenden möchten. Clojure verbietet die imperative Programmierung nicht vollständig, ist diesem Stil jedoch weniger entgegenkommend als Common Lisp.
quelle
Hier ist ein gutes Video mit einem Vergleich von Scheme (meistens Racket) und Clojure .
Um fair zu sein, hat Racket auch Syntaxzucker (zusätzliches Reader-Zeug) für Datentypen (#hash, #, eckige Klammern usw.).
Außerdem besteht Clojures einzige Möglichkeit, einen ordnungsgemäßen Tail-Aufruf zu tätigen, in der Verwendung
recur
. Dies ist der Nachteil beim Kompilieren in JVM.quelle
trampoline
für Tail Calls.