2014-12-09 13 views
6

Ich arbeite seit ein paar Monaten mit der Sprache Scala und habe bereits einige Projekte in Scala erstellt. Ich habe festgestellt, dass Scala REPL (zumindest die IntelliJ-Arbeitsblatt-Implementierung) für eine schnelle Entwicklung sehr praktisch ist. Ich kann Code schreiben, sehen, was es macht und es ist nett. Aber ich mache die Prozedur nur für Funktionen (nicht ganzes Programm). Ich kann meine Bewerbung nicht starten und sie vor Ort ändern. Oder zumindest weiß ich nicht wie (also wenn du weißt, dass du mir einen Rat geben kannst).Was ist der Unterschied zwischen Clojure REPL und Scala REPL?

Vor einigen Tagen erzählte mir mein Mitarbeiter von Clojure REPL. Er verwendet Emacs für den Entwicklungsprozess und er kann den Code vor Ort ändern und Ergebnisse sehen, ohne ihn neu zu starten. Zum Beispiel startet er den Prozess und wenn er die Implementierung einer Funktion ändert, ändert sein Code sein Verhalten ohne Neustart. Ich hätte gerne dasselbe mit der Sprache von Scala.

P.S. Ich möchte weder diskutieren, welche Sprache besser ist, noch ob die funktionale Programmierung besser ist als die objektorientierte. Ich möchte eine gute Lösung finden. Wenn Clojure die bessere Sprache für die Aufgabe ist, lass es sein.

+2

Einer wird verwendet, um Clojure zu schreiben, der andere um Scala zu schreiben. Auch: http://stackoverflow.com/questions/2471947/is-there-an-easy-way-to-get-the-scala-repl-to-relo-a-class-or-package – vptheron

+0

Es ist ein wenig schwer für mich zu wissen, wie eine richtige Antwort aussehen würde? Fragen Sie vielleicht, ob die Scala REPL Funktionen in einem laufenden Programm neu definieren kann? –

+0

Neugier, die Frage ist gut, aber der Titel ist nicht. – Mars

Antwort

18

Die kurze Antwort ist, dass Clojure entworfen wurde, um einen sehr einfachen Single-Pass-Compiler zu verwenden, der einen einzelnen s-Ausdruck oder eine Form gleichzeitig liest und kompiliert. Zum Besseren oder Schlechteren gibt es keine globale Typinformation, keine globale Typinferenz und keine globale Analyse oder Optimierung. Clojure verwendet clojure.lang.Var Instanzen, um globale Bindungen durch eine Reihe von Hashmaps von Textsymbolen zu Transaktionswerten zu erstellen. def bildet alle Erstellungsbindungen auf globaler Ebene in dieser globalen Bindungszuordnung. Wo also in Scala eine "Funktion" (Methode) zu einer Instanz oder statischen Methode einer gegebenen JVM-Klasse aufgelöst wird, ist in Clojure eine "Funktion" (def) eigentlich nur ein Verweis auf einen Eintrag in der Tabelle der var-Bindungen. Wenn eine Funktion aufgerufen wird, gibt es keine statische Verknüpfung zu einer anderen Klasse, stattdessen wird die Variable durch einen symbolischen Namen referenziert und dann dereferenziert, um eine Instanz eines Objekts zu erhalten, das dann aufgerufen wird.

Diese Indirektionsebene bedeutet, dass es möglich ist, nur eine einzelne Definition gleichzeitig neu zu bewerten, und dass die Neubewertung für alle Clients der neu definierten Variablen global sichtbar wird.

Im Vergleich, wenn sich eine Definition in Scala ändert, muss scalac die geänderte Datei neu laden, macroexpand, type infer, type check und compile. Aufgrund der Semantik des Klassenladens auf der JVM muss scalac auch alle Klassen neu laden, die von Methoden in der Klasse abhängen, die sich geändert hat. Außerdem werden alle Werte, die Instanzen der geänderten Klasse sind, zu Papierkorb.

Beide Ansätze haben ihre Stärken und Schwächen. Offensichtlich ist der Ansatz von Clojure einfacher zu implementieren, aber er zahlt laufende Kosten in Bezug auf die Leistung aufgrund fortlaufender Funktionsnachschlagoperationen, die Korrektheitsbedenken wegen fehlender statischer Typen vergessen und was Sie haben. Dies ist wohl für Kontexte geeignet, in denen viele Änderungen in einem kurzen Zeitrahmen stattfinden (interaktive Entwicklung), ist aber weniger geeignet für Kontext, wenn Code größtenteils statisch ist (Einsatz, daher Oxcart). some work I did schlägt vor, dass die Verlangsamung von Clojure-Programmen aus dem Mangel an statischer Methodenverknüpfung in der Größenordnung von 16-25% liegt. Das heißt nicht Clojure langsam oder Scala schnell zu nennen, sie haben nur unterschiedliche Prioritäten.

Scala entscheidet sich dafür, mehr Arbeit zu leisten, damit die kompilierte Anwendung besser funktioniert, was wohl besser für die Anwendungsbereitstellung geeignet ist, wenn wenig oder gar kein Nachladen stattfindet, aber ein Nachteil ist, wenn Sie viele kleine Änderungen vornehmen wollen .

Einige Materialien, die ich zur Verfügung habe, um Clojure-Code mehr oder weniger cronological durch Veröffentlichungsreihenfolge zu kompilieren, da Nicholas meine GSoC-Arbeit viel beeinflusste.

Was ich lässt mich annehmen, in der unglückliche Ort, einfach zu sagen: "Es tut mir leid, Scala war dafür nicht so konzipiert C ljure war "in Bezug auf Code Hot Swapping.

+1

Gilad Bracha und andere Koryphäen aus den Smalltalk- und Lisp-Welten haben dieses Mantra, dass "statische Typen Kopplung sind", und dies ist ein weiteres Beispiel dafür. Es ist - zumindest nach unserem derzeitigen Kenntnisstand - einfach nicht möglich, eine lebhafte Umgebung für eine statisch typisierte Sprache zu implementieren, während dynamisch typisierte Sprachen * extrem * leistungsstarke, lebendige Umgebungen haben, siehe die MIT Lisp Machine, Squeak/Pharo Smalltalk , Neusprech, Dan Ingalls Lebhafter Kern oder die Selbstwelt. –

+0

Danke euch allen sehr! – Curiosity

+0

@ JörgWMittag Es ist immer ein Kompromiss zwischen dynamisch und statisch überprüfbar zu sein. Manchmal willst du eins, manchmal willst du das andere. Ich neige dazu, mich auf die Seite der statischen Typisierung zu stützen - hauptsächlich, weil ich einige Bugs gesehen habe, die sogar in Java auftreten, weil das Typsystem zu nachsichtig ist. Damit sind die Vorteile des dynamischen Tippens nicht zu verachten, für mich überwiegen die Vorteile der statischen Eingabe mehr. YMMV – Cubic