Eine Read-Eval-Print-Schleife ( REPL ), auch interaktive Toplevel- oder Sprachshell genannt , ist eine einfache interaktive Programmierumgebung , die Benutzereingaben entgegennimmt, diese ausführt und das Ergebnis an den Benutzer zurückgibt. Ein in einer REPL-Umgebung geschriebenes Programm wird stückweise ausgeführt. [ 1 ] Der Begriff bezieht sich üblicherweise auf Programmierschnittstellen, die der klassischen interaktiven Lisp- Maschinenumgebung oder Common Lisp mit der SLIME -Entwicklungsumgebung ähneln. Gängige Beispiele sind Kommandozeilen- Shells und ähnliche Umgebungen für Programmiersprachen . Diese Technik ist sehr charakteristisch für Skriptsprachen , [ 2 ] obwohl deren Eigenschaften stark variieren können.
Geschichte
Der Ausdruck READ-EVAL-PRINT-Zyklus wurde von L. Peter Deutsch und Edmund Berkeley für eine 1964 entwickelte Lisp -Implementierung auf dem PDP-1 verwendet . [ 3 ] Nur einen Monat später veröffentlichte Project Mac einen Bericht von Joseph Weizenbaum (dem Entwickler von ELIZA , dem weltweit ersten Chatbot), in dem er eine REPL-basierte Sprache namens OPL-1 beschrieb, die in seiner Fortran-SLIP -Sprache auf dem Compatible Time Sharing System (CTSS) implementiert war . [ 4 ] [ 5 ] [ 6 ]
Das 1974 erschienene Maclisp -Referenzhandbuch von David A. Moon belegt auf Seite 89 die Verwendung einer „Read-eval-print loop“, verwendet aber nicht das Akronym REPL. [ 7 ]
Seit mindestens den 1980er Jahren sind die Abkürzungen REP Loop und REPL im Kontext von Scheme belegt . [ 8 ] [ 9 ]
Überblick
In einer REPL (Read-Eval-Print-Loop) gibt der Benutzer einen oder mehrere Ausdrücke (anstatt einer gesamten Kompilierungseinheit ) ein, die von der REPL ausgewertet und die Ergebnisse angezeigt werden. [ 1 ] Der Name Read-Eval-Print-Loop leitet sich von den Namen der Lisp-Primitivfunktionen ab, die diese Funktionalität implementieren:
- Die Lesefunktion nimmt einen Ausdruck vom Benutzer entgegen und wandelt ihn in eine Datenstruktur im Speicher um. Beispielsweise kann der Benutzer den S-Ausdruck eingeben, der in eine verkettete Liste mit vier Datenelementen
(+ 1 2 3)umgewandelt wird . - Die Funktion `eval` nimmt diese interne Datenstruktur und wertet sie aus. In Lisp bedeutet die Auswertung eines S-Ausdrucks, der mit dem Namen einer Funktion beginnt, den Aufruf dieser Funktion mit den Argumenten, aus denen der restliche Ausdruck besteht. Die Funktion
+wird also mit den Argumenten aufgerufen1 2 3und liefert das Ergebnis6. - Die Funktion `print` nimmt das Ergebnis von `eval` und gibt es dem Benutzer aus. Bei komplexen Ausdrücken kann die Ausgabe formatiert werden , um das Verständnis zu erleichtern.
Die Entwicklungsumgebung kehrt dann in den Lesezustand zurück, wodurch eine Schleife entsteht, die endet, wenn das Programm geschlossen wird.
REPLs erleichtern exploratives Programmieren und Debuggen, da der Programmierer das ausgegebene Ergebnis überprüfen kann, bevor er entscheidet, welchen Ausdruck er für den nächsten Lesevorgang verwendet. Die Lese-Auswertungs-Ausgabe-Schleife bindet den Programmierer häufiger ein als der klassische Bearbeitungs-Kompilierungs-Ausführungs-Debug-Zyklus.
Da die Ausgabefunktion dasselbe Textformat verwendet wie die Eingabefunktion , lassen sich die meisten Ergebnisse in einem Format ausgeben, das sich in die REPL kopieren und einfügen lässt. Manchmal ist es jedoch notwendig, Darstellungen von Elementen auszugeben, die nicht sinnvoll eingelesen werden können, wie beispielsweise ein Socket-Handle oder eine komplexe Klasseninstanz. In diesen Fällen muss eine Syntax für nicht lesbare Objekte existieren. In Python ist dies die <__module__.class instance>Notation `unlesbar`, in Common Lisp die #<whatever>Form `unlesbar`. Die REPLs von CLIM , SLIME und der Symbolics Lisp Machine können ebenfalls nicht lesbare Objekte einlesen. Sie protokollieren für jede Ausgabe, welches Objekt ausgegeben wurde. Beim späteren Einlesen des Codes wird das Objekt aus der Ausgabe extrahiert.
REPLs können für jede textbasierte Sprache erstellt werden. Die Unterstützung kompilierter Sprachen durch REPLs wird üblicherweise durch die Implementierung eines Interpreters auf einer virtuellen Maschine erreicht, die eine Schnittstelle zum Compiler bereitstellt. Beispielsweise enthielt Java ab JDK 9 die JShell als Kommandozeilenschnittstelle. Für diverse andere Sprachen stehen Drittanbieter-Tools zum Download bereit, die eine ähnliche Shell-Interaktion mit der Sprache ermöglichen, wobei sich die Funktionen jedoch stark unterscheiden können.
Verwendung
Als Shell ermöglicht eine REPL-Umgebung (Read-Experience Language) den Zugriff auf relevante Funktionen eines Betriebssystems und bietet darüber hinaus Programmiermöglichkeiten. Am häufigsten werden REPLs außerhalb von Betriebssystem-Shells für interaktives Prototyping eingesetzt . [ 10 ] Weitere Anwendungsgebiete sind mathematische Berechnungen, die Erstellung von Dokumenten mit wissenschaftlichen Analysen (z. B. IPython ), interaktive Softwarewartung, Benchmarking und die Erforschung von Algorithmen.
Lisp-Besonderheiten
Durchführung
Eine Minimaldefinition in Common Lisp lautet:
( loop ( print ( eval ( read ))))Die Funktion readwartet auf Benutzereingaben, evalwertet diese aus, printgibt das Ergebnis aus und loopläuft in einer Endlosschleife. Sie können (+ 1 1)die Schleife mit `.` beenden C-c.
Funktionalität
Typische Funktionen einer Common Lisp REPL umfassen:
- Historie der Inputs und Outputs.
- Für die Eingabeausdrücke und Ergebnisse werden Variablen festgelegt. Diese Variablen stehen auch in der REPL zur Verfügung. Beispielsweise
*bezieht sich `` in Common Lisp auf das letzte Ergebnis**und***`` auf die Ergebnisse davor. - REPL-Ebenen. In vielen Lisp-Systemen wird bei einem Fehler während des Lesens, Auswertens oder Ausgebens eines Ausdrucks das System nicht mit einer Fehlermeldung auf die oberste Ebene zurückgeworfen. Stattdessen wird im Fehlerkontext eine neue REPL eine Ebene tiefer gestartet. Der Benutzer kann dann das Problem untersuchen, beheben und – falls möglich – fortfahren. Tritt in einer solchen Debug-REPL ein Fehler auf, wird eine weitere REPL, wiederum eine Ebene tiefer, gestartet. Oft bietet die REPL spezielle Debug-Befehle.
- Fehlerbehandlung . In Common Lisp öffnet die REPL bei einem Fehler einen interaktiven Debugger. Dieser ermöglicht die Untersuchung des Aufrufstapels, das Springen zur fehlerhaften Funktion, deren Korrektur, die Neukompilierung und die Fortsetzung der Ausführung, ohne das gesamte Programm neu starten zu müssen. Der Debugger bietet außerdem Neustarts. Diese Neustarts können verwendet werden, um zu einer bestimmten REPL-Ebene zurückzukehren oder einen anderen Eingabewert zu verwenden.
- Mausgesteuerte Ein- und Ausgabe von Datenobjekten.
- Eingabebearbeitung und kontextspezifische Vervollständigung für Symbole, Pfadnamen, Klassennamen und andere Objekte.
- Hilfe und Dokumentation zu den Befehlen.
- Variablen zur Steuerung des Readers. Die Variable *read-base* steuert beispielsweise, in welcher Basis die Zahlen standardmäßig gelesen werden.
- Variablen zur Steuerung des Druckers. Beispiel: maximale Länge oder maximale Tiefe der zu druckenden Ausdrücke.
- Zusätzliche Befehlssyntax. Einige REPLs verfügen über Befehle, die nicht der S-Ausdruckssyntax folgen, sondern häufig mit Lisp-Daten als Argumenten arbeiten.
- Grafische REPLs. Einige Lisp-REPLs (der CLIM Listener ist ein Beispiel und in geringerem Maße SLIME ) akzeptieren auch grafische Ein- und Ausgabe.
- Verbindung zu einem entfernt laufenden Programm. Es ist möglich, eine Verbindung zu einem Common-Lisp-Programm herzustellen, das auf einem anderen Rechner läuft, und mit diesem zu interagieren. Dies ermöglicht es, seinen internen Zustand zu untersuchen, Parameter zu ändern oder sogar neuen Code zu kompilieren und das System zu aktualisieren.
Kombination von Quelldateien und REPL-Entwicklung
Entwickler von Lisp-Anwendungen schreiben oder kopieren ihren Code üblicherweise nicht direkt in eine REPL (Read-Exchange Plough). Sie nutzen die REPL für schnelle Tests, zum Debuggen und um ein laufendes System zu erkunden. Ihre Anwendung schreiben sie in einer Quelldatei unter Versionskontrolle und kompilieren ihren Code interaktiv mithilfe von Befehlen oder Tastenkombinationen. Der Lisp-Prozess läuft dabei, ist mit dem Editor verbunden und kompiliert neuen Code dynamisch, ohne dass ein Neustart erforderlich ist.
In Common Lisp kompilieren Entwickler üblicherweise die aktuell bearbeitete Funktion. Alternativ können sie auch eine ganze Datei oder ein komplettes Projekt kompilieren. Nach der Kompilierung einer Funktion können Typwarnungen auftreten (insbesondere bei der SBCL -Implementierung). Die neu erstellte Funktion lässt sich dann über die REPL aufrufen. Tritt ein Fehler auf, steht ein interaktiver Debugger zur Verfügung.
Das Kompilieren und Testen einer einzelnen Funktion in der REPL ist im Vergleich zu anderen Prozessen sehr schnell. Der Zyklus aus dem Schreiben, Kompilieren und Testen einer neuen Funktion ist kurz und interaktiv, wodurch er sich gut für die Entwicklung eignet. Außerdem bleibt der Anwendungszustand während der Entwicklung erhalten.
Nur wenn sie sich dazu entscheiden, führen sie die gesamte Anwendung von Grund auf aus oder kompilieren sie.
Siehe auch
Referenzen
- ^ a b Grillmeyer, O. (2013). Exploring Computer Science with Scheme . Undergraduate Texts in Computer Science. Springer New York. S. 239. ISBN 978-1-4757-2937-5Abgerufen am 26.06.2021 .
Die zentrale Komponente des Scheme-Interpreters ist die Read-Eval-Print-Schleife . Befehle werden eingelesen, ausgewertet und anschließend ausgegeben.
- ^ Hey, Tony ; Pápay, Gyuri (2014). The Computing Universe: A Journey through a Revolution . Cambridge University Press. S. 76. ISBN 978-1-316-12322-5„Ein Hauptmerkmal moderner Skriptsprachen ist ihre Interaktivität, die mitunter als REPL -Programmierumgebung bezeichnet wird. … Die Merkmale der einfachen Bedienbarkeit und der sofortigen Ausführung in einer REPL-Umgebung werden manchmal als Definition einer Skriptsprache angesehen.“
{{cite book}}: CS1 Wartung: Postscript ( Link ) - ^ L. Peter Deutsch; Edmund Berkeley, Die LISP-Implementierung für den PDP-1-Computer (PDF) , S. 15
- ^ Joseph Weizenbaum, OPL-I: EIN OFFENES PROGRAMMIERSYSTEM IM RAHMEN VON CTSS
- ^ Beide Projekte wurden vermutlich 1963 durchgeführt, also lange vor dem Erscheinen der jeweiligen Veröffentlichungen. Die genauen Erfindungsdaten lassen sich jedoch nicht bestimmen.
- Es besteht eine komplexe und interessante Beziehung zwischen Lisp und SLIP, die beide namensgebende „Listenverarbeitungssprachen“ sind und von Wissenschaftlern des MIT entwickelt wurden: Shrager, Jeff (2024), ELIZA Reinterpreted: The world's first chatbot was not intended as a chatbot at all , arXiv : 2406.17650
- ^ David A. Moon (8. April 1974), MACLISP-Referenzhandbuch (PDF) , S. 89
- ^ Smith, Jerry D. (1988). Einführung in Scheme . Englewood Cliffs , NJ: Prentice Hall. S. 8. ISBN 978-0-13-496712-7Die
- ^ Hanson, Chris (1986). „rep.scm – Erste Revision des MIT-Schemes von 1986“ . GitHub . Abgerufen am 11. Juni 2023 .
- ^ van Binsbergen, L. Thomas; Verano Merino, Mauricio; Jeanjean, Pierre; van der Storm, Tijs; Combemale, Benoit; Barais, Olivier (17.11.2020). „Ein prinzipiengeleiteter Ansatz für REPL-Interpreter“. Proceedings of the 2020 ACM SIGPLAN International Symposium on New Ideas, New Paradigms, and Reflections on Programming and Software (PDF) . New York, NY, USA: ACM. S. 84–100 . doi : 10.1145/3426428.3426917 . ISBN 978-1-4503-8178-9Die
Externe Links
- Paul Graham hat eine Beschreibung einer REPL-Implementierung in Common Lisp verfasst .
- Joël Franusic Online-REPs-und-REPLs-Liste