scheme
Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
| Beide Seiten der vorigen RevisionVorhergehende ÜberarbeitungNächste Überarbeitung | Vorhergehende Überarbeitung | ||
| scheme [2013-10-05 22:56:51] – [CHICKEN] manfred | scheme [2021-04-02 00:22:07] (aktuell) – [Racket] manfred | ||
|---|---|---|---|
| Zeile 1: | Zeile 1: | ||
| + | ====== Scheme ====== | ||
| + | |||
| + | **Aussprache: | ||
| + | |||
| + | Die erste funktionale Programmiersprache, | ||
| + | |||
| + | //Scheme// ist keine rein-funktionale Programmiersprache. Vielmehr enthält sie auch Konzepte der imperativen Programmierung (Schleifen, Variablen). | ||
| + | |||
| + | **// | ||
| + | |||
| + | Entwickelt wurde Scheme am // | ||
| + | |||
| + | * [[http:// | ||
| + | * [[http:// | ||
| + | * [[http:// | ||
| + | * [[http:// | ||
| + | * [[http:// | ||
| + | * [[http:// | ||
| + | * [[http:// | ||
| + | * [[http:// | ||
| + | * [[http:// | ||
| + | |||
| + | Die gebräuchlichen Dateiendungen für die Quellcodedateien von //Scheme// lauten **.scm** bzw. **.ss**. | ||
| + | |||
| + | |||
| + | ===== Syntax ===== | ||
| + | |||
| + | * [[http:// | ||
| + | * [[http:// | ||
| + | |||
| + | In Scheme gibt es nur Prefix-Operatoren im Stil von (funktion argumente) oder (operator operanden…). Eine simple Addition lautet: | ||
| + | |||
| + | (+ 2 3) ---> 5 | ||
| + | |||
| + | Hierbei wird der Ausdruck 3 evaluiert, dann 2, und dann der ganze Ausdruck zu 5 evaluiert. | ||
| + | Analog verhält es sich bei: | ||
| + | |||
| + | (+ 2 (+ 1 2)) ---> 5 | ||
| + | |||
| + | Globale Variablen können mit | ||
| + | |||
| + | (define x 3) | ||
| + | |||
| + | definiert werden. | ||
| + | Lokale Variablenbindungen lassen sich mit | ||
| + | |||
| + | (let ((x 4) (y 5)) body) | ||
| + | |||
| + | definieren, wobei die globale Variable x von der Lokalen überdeckt wird. body ist der Bereich, in dem die lokalen Variablen x und y sichtbar sind. | ||
| + | |||
| + | (let ((x 4) (y 5)) (+ x y)) | ||
| + | |||
| + | Auch in Scheme gibt es Kontrollstrukturen wie if, else case, do, cond. Dabei ist do eine Schleife. Anders als in C gibt es hier keine Laufbedingung sondern eine Abbruchbedingung. Das kann anfangs zu Irritationen führen. | ||
| + | |||
| + | (do ((x 0 (+ x 1))) | ||
| + | ((= x 10) (display " | ||
| + | (display x)) | ||
| + | |||
| + | Die Schleife läuft solange, bis x den Wert 10 erreicht. | ||
| + | |||
| + | |||
| + | ===== integrierte Entwicklungsumgebung (IDE) ===== | ||
| + | |||
| + | |||
| + | ==== DrScheme / PLT Scheme ==== | ||
| + | |||
| + | **DrScheme** ist eine integrierte Entwicklungsumgebung (IDE) für die Programmiersprache //Scheme//. Die Software ist mit einer grafischen Benutzeroberfläche ausgestattet und ist Bestandteil von **PLT Scheme**. DrScheme kommt oft in Informatikkursen von Universitäten zum Einsatz. | ||
| + | |||
| + | // | ||
| + | // | ||
| + | Für Anfänger bietet das Projekt die Sprache //Lazy Scheme// an. | ||
| + | |||
| + | * [[http:// | ||
| + | * [[http:// | ||
| + | * [[http:// | ||
| + | * [[http:// | ||
| + | * [[http:// | ||
| + | * [[http:// | ||
| + | * [[http:// | ||
| + | |||
| + | Start mit DrScheme (http:// | ||
| + | ------------------ | ||
| + | 1. Sprache / Sprache auswählen... | ||
| + | | ||
| + | Module | ||
| + | 2. im oberen Text-Fenster folgendes eingeben: | ||
| + | #lang scheme | ||
| + | 3. jetzt oben rechts auf " | ||
| + | um die Sprache bzw. das Modul zu aktivieren | ||
| + | | ||
| + | Diese Angaben brauchen beim nächsten Start von DrScheme nicht | ||
| + | erneut gemacht werden, es werden beim Start immer die letzten | ||
| + | Einstellungen wieder hergestellt. | ||
| + | | ||
| + | Jetzt kann man im unteren Textfenster Scheme-Code eingeben. | ||
| + | Will man ein Programm schreiben, kann man im unteren Fenster | ||
| + | kleine Codeteile testen und sie dann im oberen Fenster einfühgen. | ||
| + | Drückt man auf Start, ist im unteren Fenster die Ausgabe zu sehen. | ||
| + | Will man das Programm aus dem oberen Fenster abspeichern, | ||
| + | man auf Speichern (Diskettensymbol) und vergibt einen Namen der | ||
| + | auf " | ||
| + | |||
| + | |||
| + | === Dateioperationen === | ||
| + | |||
| + | Im folgenden ein PLT-Scheme-Test von mir, in dem ich diverse Möglichkeiten ausprobiert habe wie man Ausgaben in Dateien schreiben kann. | ||
| + | |||
| + | #lang scheme | ||
| + | | ||
| + | (require scheme/ | ||
| + | (define DATEIPFAD " | ||
| + | | ||
| + | ; eine neue Datei wird zum schreiben angelegt | ||
| + | (define o (open-output-file DATEIPFAD #: | ||
| + | (display " | ||
| + | (newline o) | ||
| + | (display " | ||
| + | (write-char #\space o) | ||
| + | (display 'world o) | ||
| + | (newline o) | ||
| + | (display "Hallo Welt!" o) | ||
| + | (newline o) | ||
| + | ;Datei wird geschlossen | ||
| + | (close-output-port o) | ||
| + | | ||
| + | (port-count-lines-enabled 'any) | ||
| + | | ||
| + | ; vorhandene Datei wird zum lesen geöffnet | ||
| + | ;(define i (open-input-file DATEIPFAD #: | ||
| + | ;;; nächstes Wort lesen | ||
| + | ;;; " | ||
| + | ;(display (read i)) | ||
| + | ;(display (read i)) | ||
| + | ;(display (read i)) | ||
| + | ;(display (read i)) | ||
| + | ;(display (read i)) | ||
| + | ;(newline) | ||
| + | ; Datei wird wieder geschlossen | ||
| + | ; | ||
| + | | ||
| + | ; vorhandene Datei wird zum lesen geöffnet | ||
| + | ;(define i (open-input-file DATEIPFAD #: | ||
| + | ;;; nächste Zeile als String in doppelten Anführungszeichen ausgeben | ||
| + | ;(read-line i) | ||
| + | ;(read-line i) | ||
| + | ;(read-line i) | ||
| + | ;(read-line i) | ||
| + | ; | ||
| + | | ||
| + | ; Trennlinie ziehen | ||
| + | ;(display " | ||
| + | ;(newline) | ||
| + | | ||
| + | ;;; ganze Zeilen ausgeben | ||
| + | ; vorhandene Datei wird zum lesen geöffnet | ||
| + | (define j (open-input-file DATEIPFAD #: | ||
| + | (port-next-location j) | ||
| + | ;;; jedes " | ||
| + | (display (read-line j 'any)) | ||
| + | (newline) | ||
| + | (port-next-location j) | ||
| + | (display (read-line j 'any)) | ||
| + | (newline) | ||
| + | (port-next-location j) | ||
| + | (display (read-line j 'any)) | ||
| + | (newline) | ||
| + | (port-next-location j) | ||
| + | (display (read-line j 'any)) | ||
| + | (newline) | ||
| + | (port-next-location j) | ||
| + | (display (read-line j 'any)) | ||
| + | (newline) | ||
| + | (port-next-location j) | ||
| + | (close-input-port j) | ||
| + | | ||
| + | ;;; eine Eingabe von der Tastatur einlesen | ||
| + | ; | ||
| + | | ||
| + | ; Trennlinie ziehen | ||
| + | (display " | ||
| + | (newline) | ||
| + | | ||
| + | ;;; ganze Datei ausgeben | ||
| + | ; vorhandene Datei wird zum lesen geöffnet | ||
| + | (define k (open-input-file DATEIPFAD #: | ||
| + | ; | ||
| + | (port-count-lines! k) | ||
| + | ;;; jedes " | ||
| + | ;(display (read-line k ' | ||
| + | (display (read-line k ' | ||
| + | ;;; 1. Ausgabe: nächste Zeilennummer | ||
| + | ;;; 2. Ausgabe: nächste Spalte | ||
| + | ;;; 3. Ausgabe: nächste Position | ||
| + | (port-next-location k) | ||
| + | (close-input-port k) | ||
| + | | ||
| + | ; aktueller Speicherverbrauch | ||
| + | (define MEM (current-memory-use)) | ||
| + | (display " | ||
| + | (display MEM) | ||
| + | (newline) | ||
| + | | ||
| + | ; Trennlinie ziehen | ||
| + | (display " | ||
| + | (newline) | ||
| + | | ||
| + | ; Größe der Datei in byte | ||
| + | (display (file-size DATEIPFAD)) | ||
| + | (newline) | ||
| + | | ||
| + | ; Zeilenweise Ausgabe | ||
| + | (display (file-exists? | ||
| + | ;(display (file-> | ||
| + | (newline) | ||
| + | | ||
| + | ; in das Verzeichnis "/ | ||
| + | ; | ||
| + | | ||
| + | ; Trennlinie ziehen | ||
| + | (display " | ||
| + | (newline) | ||
| + | | ||
| + | (display "Datei Zeichenweise ausgeben" | ||
| + | (newline) | ||
| + | (let ((ZEICHEN (file-size DATEIPFAD))) | ||
| + | (call-with-input-file DATEIPFAD | ||
| + | (lambda (T) | ||
| + | (let loop ((i 0)) | ||
| + | (unless (>= i ZEICHEN) | ||
| + | ;;; char-Code des nächsten Zeichens | ||
| + | (display (read-char T)) | ||
| + | ; | ||
| + | ;;; Tastaturcode des nächsten Zeichens | ||
| + | ;(display (read-byte-or-special T)) | ||
| + | ;(newline) | ||
| + | ; | ||
| + | (loop (+ i 1)) | ||
| + | ) | ||
| + | ) | ||
| + | ) | ||
| + | ) | ||
| + | ) | ||
| + | | ||
| + | ; Trennlinie ziehen | ||
| + | (display " | ||
| + | (newline) | ||
| + | | ||
| + | (display "Datei Zeilenweise ausgeben" | ||
| + | (newline) | ||
| + | (call-with-input-file DATEIPFAD | ||
| + | (lambda (aport) | ||
| + | (let loop ((lline (read-line aport ' | ||
| + | (when (not (eof-object? | ||
| + | (display lline) | ||
| + | (newline) | ||
| + | (loop (read aport)) | ||
| + | ) | ||
| + | ) | ||
| + | ) | ||
| + | ) | ||
| + | |||
| + | Die Ausgabe wurde in die Datei **test.txt** geschrieben: | ||
| + | |||
| + | cat test.txt | ||
| + | Yoda | ||
| + | hello world | ||
| + | Hallo Welt! | ||
| + | |||
| + | |||
| + | ===== Compiler ===== | ||
| + | |||
| + | |||
| + | ==== CHICKEN ==== | ||
| + | |||
| + | * [[http:// | ||
| + | * [[https:// | ||
| + | * [[http:// | ||
| + | |||
| + | |||
| + | === Chicken als Taschenrechner === | ||
| + | |||
| + | echo "(* 12 3000)" | csi -q | ||
| + | |||
| + | |||
| + | === hallo_welt.scm === | ||
| + | |||
| + | (display "Hallo Welt! ") | ||
| + | (display (+ 3 5)) | ||
| + | (newline) | ||
| + | (define nachricht1 "' | ||
| + | (write nachricht1) | ||
| + | (newline) | ||
| + | (display nachricht1) | ||
| + | (newline) | ||
| + | (define nachricht2 " | ||
| + | (display nachricht2) | ||
| + | (newline) | ||
| + | (write (+ 3 4)) | ||
| + | (newline) | ||
| + | |||
| + | |||
| + | dynamisch gelinkt (ausführbare Datei ist 12kB groß): | ||
| + | |||
| + | csc hallo_welt.scm | ||
| + | |||
| + | |||
| + | link with static CHICKEN libraries: | ||
| + | |||
| + | csc -static-libs hallo_welt.scm | ||
| + | |||
| + | |||
| + | **generate completely statically linked executable** (ausführbare Datei ist 1,8MB groß): | ||
| + | |||
| + | csc -static hallo_welt.scm | ||
| + | |||
| + | |||
| + | ./ | ||
| + | Hallo Welt! 8 | ||
| + | "' | ||
| + | 'Hallo Welt!', | ||
| + | "Hallo Welt!", | ||
| + | 7 | ||
| + | |||
| + | |||
| + | === datei.scm === | ||
| + | |||
| + | ; http:// | ||
| + | ; http:// | ||
| + | | ||
| + | | ||
| + | ; unbound variable: create-directory | ||
| + | ; unbound variable: change-directory | ||
| + | ; unbound variable: current-directory | ||
| + | ; | ||
| + | ; | ||
| + | ; | ||
| + | | ||
| + | | ||
| + | | ||
| + | (define o (open-output-file " | ||
| + | | ||
| + | (display " | ||
| + | (newline o) | ||
| + | | ||
| + | (display " | ||
| + | (write-char #\space o) | ||
| + | (display 'world o) | ||
| + | (newline o) | ||
| + | | ||
| + | (display "Hallo Welt!" o) | ||
| + | (newline o) | ||
| + | | ||
| + | (close-output-port o) | ||
| + | | ||
| + | | ||
| + | | ||
| + | (define i (open-input-file " | ||
| + | ; (read-char i) | ||
| + | | ||
| + | (define j (read i)) | ||
| + | (display j) | ||
| + | (newline) | ||
| + | | ||
| + | (close-input-port i) | ||
| + | | ||
| + | | ||
| + | | ||
| + | ; Datei automatisch öffnen und schließen | ||
| + | (call-with-input-file " | ||
| + | (lambda (T) | ||
| + | (define ANZAHL 7) | ||
| + | ;(define ANZAHL (vector-length T)) | ||
| + | ;(display ANZAHL) | ||
| + | ;(newline) | ||
| + | (let loop ((i 0)) | ||
| + | (unless (>= i ANZAHL) | ||
| + | (display (read T)) | ||
| + | (newline) | ||
| + | (loop (+ i 1)) | ||
| + | ) | ||
| + | ) | ||
| + | ) | ||
| + | ) | ||
| + | | ||
| + | | ||
| + | ; unbound variable: change-directory | ||
| + | ;(display (file-stat " | ||
| + | | ||
| + | | ||
| + | ;(define argv-count (vector-length argv)) | ||
| + | ; | ||
| + | ;(let loop ((i 0)) | ||
| + | ; (unless (>= i argv-count) | ||
| + | ; (display (vector-ref argv i)) | ||
| + | ; (newline) | ||
| + | ; (loop (+ i 1)))) | ||
| + | |||
| + | |||
| + | === argumente.scm === | ||
| + | |||
| + | * [[http:// | ||
| + | |||
| + | (display "Sie haben \"" | ||
| + | (display (car (argv))) | ||
| + | (display " | ||
| + | (newline) | ||
| + | (newline) | ||
| + | (write (car (argv))) | ||
| + | (newline) | ||
| + | (print "print " (car (argv))) | ||
| + | (newline) | ||
| + | (display (flatten (argv) )) | ||
| + | (newline) | ||
| + | | ||
| + | | ||
| + | | ||
| + | (define argv-count (vector-length argv)) | ||
| + | | ||
| + | (let loop ((i 0)) | ||
| + | (unless (>= i argv-count) | ||
| + | (display (vector-ref argv i)) | ||
| + | (newline) | ||
| + | (loop (+ i 1)))) | ||
| + | |||
| + | |||
| + | === squares.scm === | ||
| + | |||
| + | (define (square x) (* x x)) | ||
| + | (display (square 3)) | ||
| + | (newline) | ||
| + | |||
| + | |||
| + | === squares1.scm === | ||
| + | |||
| + | (do | ||
| + | ; Initialize variables | ||
| + | ( | ||
| + | (i 1 (+ i 1)) | ||
| + | ) | ||
| + | | ||
| + | ; while condition | ||
| + | ( | ||
| + | (> i 10) | ||
| + | ) | ||
| + | | ||
| + | ; loop body | ||
| + | (display (* i i)) | ||
| + | (display " " | ||
| + | ) | ||
| + | |||
| + | |||
| + | === squares2.scm === | ||
| + | |||
| + | (do ( (i 1 (+ i 1)) ) ( (> i 10) ) | ||
| + | (display (* i i)) | ||
| + | (newline) | ||
| + | ) | ||
| + | |||
| + | |||
| + | === squares_lambda.scm === | ||
| + | |||
| + | (define square (lambda (x) (* x x))) | ||
| + | |||
| + | |||
| + | === define.scm === | ||
| + | |||
| + | (define pi 3.14159) | ||
| + | (define radius 10) | ||
| + | (define umfang (* 2 pi radius)) | ||
| + | (display umfang) | ||
| + | (newline) | ||
| + | |||
| + | |||
| + | === foo.scm === | ||
| + | |||
| + | (define (fac n) | ||
| + | (if (zero? n) | ||
| + | 1 | ||
| + | (* n (fac (- n 1))))) | ||
| + | (write (fac 10)) | ||
| + | (newline) | ||
| + | |||
| + | |||
| + | === status.scm === | ||
| + | |||
| + | ; ist wahr: #t | ||
| + | (display (= 2 (+ 4 -2))) | ||
| + | (newline) | ||
| + | | ||
| + | ; ist falsch #f | ||
| + | (display (< 2 (+ 4 -2))) | ||
| + | (newline) | ||
| + | | ||
| + | ; ist wahr: #t | ||
| + | (display (< 1 (+ 4 -2))) | ||
| + | (newline) | ||
| + | | ||
| + | ; so vergleicht man Symbole | ||
| + | (display (eq? 2 (+ 4 -2))) | ||
| + | (newline) | ||
| + | | ||
| + | ; so vergleicht man Objekte, Zahlen, Zeichen und Zeichenketten | ||
| + | (display (eqv? 2 (+ 4 -2))) | ||
| + | (newline) | ||
| + | |||
| + | |||
| + | === env.scm === | ||
| + | |||
| + | (define HOME (getenv " | ||
| + | (display HOME) | ||
| + | (newline) | ||
| + | | ||
| + | (define shell (getenv " | ||
| + | | ||
| + | (display shell) | ||
| + | (newline) | ||
| + | |||
| + | |||
| + | ==== MzScheme ==== | ||
| + | |||
| + | mzc --exe hallo_welt hallo_welt.ss | ||
| + | mzc --gui-exe hallo_welt hallo_welt.ss | ||
| + | |||
| + | |||
| + | ==== Racket ==== | ||
| + | |||
| + | Racket ist eine multi-paradigmatische Programmiersprache in der Lisp-Scheme-Familie. Sie ist Nachfolger des Scheme-Dialekts PLT Scheme. Racket ist auch eine integrierte Entwicklungsumgebung (IDE) mit umfangreicher Bibliothek. | ||
| + | |||
| + | * [[https:// | ||
| + | * [[http:// | ||
| + | |||
| + | |||
| + | ==== GNU-Guile - Scheme als GNU-Standard-Programmiersprache ==== | ||
| + | |||
| + | * [[http:// | ||
| + | * [[http:// | ||
| + | |||
| + | //GNU-Guile (kurz Guile, selten Guile Scheme)// ist ein Interpreter für die Programmiersprache //Scheme//, einen LISP-Dialekt. //Guile// ist als Programmbibliothek implementiert, | ||
| + | |||
| + | Der Guile-Interpreter erweitert Scheme unter anderem um folgende Fähigkeiten: | ||
| + | |||
| + | * Ein erweitertes Modulsystem | ||
| + | * Vollen Zugriff auf POSIX-Systemaufrufe | ||
| + | * Netzwerkunterstützung | ||
| + | * Multithreading | ||
| + | * Dynamisches Linken | ||
| + | * Eine Schnittstelle zur Ausführung Scheme-fremder Funktionsaufrufe | ||
| + | * Verbesserte Verarbeitung von Zeichenketten | ||
| + | |||
| + | Es gibt auch noch zwei grundsätzliche Unterschiede zur Scheme Definition([Clinger]): | ||
| + | |||
| + | * Guile ist case sensitive | ||
| + | * eine leere Liste '() unterscheidet sich nicht von falsch #f | ||
| + | |||
| + | In Zukunft soll Guile auch andere Skriptsprachen wie Perl und PHP unterstützen. Zurzeit wird jedoch CTAX unterstützt, | ||
| + | |||
| + | Guile unterstützt XML, XPath, und XSLT, die //Forms// von SXML, SXPath und SXSLT. Die S-expression-basierte XML Verarbeitung wird ebenfalls unterstützt. | ||
| + | |||
| + | === Geschichte === | ||
| + | |||
| + | Die Ursprünge von Guile liegen in einer Diskussion, die von Richard Stallman gestartet wurde und die später unter dem Namen „the Tcl Wars“ bekannt geworden ist: Stallman behauptete, dass Tcl nicht leistungsfähig genug sei, um als Erweiterungsprache zu dienen. Aus diesem Grund startete er das Guile Projekt. Damals existierte zwar die Scheme-Definition, | ||
| + | |||
| + | Die ersten Versionen wurden vor 1995 von SIOD („Scheme in One Defun“) und dem SCM-Interpreter abgespalten. | ||
