Aus Linux-Magazin 05/2001

Shell-Scripting mit Scheme

Abb. 1: Eine von LAML erzeugte Tabelle.

Scripting funktioniert nicht nur bei den üblichen Verdächtigen wie Bash, Korn-Shell und Python, sondern auch mit Scheme. Im Zentrum des Artikels stehen darum die Shell-Programmierung mit Scheme sowie die Programmierung fürs Internet.

Die Scheme-Shell Scsh (http://www-swiss.ai.mit.edu/ftpdir/scsh) wurde speziell für das Unix-Scripting entworfen; für die interaktive Benutzung ist sie in ihrer jetzigen Form bei weitem nicht so gut zu gebrauchen wie zum Beispiel die Bash oder Z-Shell. Es gibt weitere Implementierungen in Lisp-Sprachen. Für die hartgesottenen Emacs-Fans sei auf die Eshell verwiesen, eine Shell für Emacs in Emacs Lisp (http://www.emacs.org/~johnw/eshell.tar.gz).

Benutzer einer Debian-Installation können auf ein HDEB-Paket der Scheme-Shell zurückgreifen, Benutzer einer RPM-basierten Distribution müssen den Weg über die Quellen (ftp://ftp-swiss.ai.mit.edu/pub/su/scsh/scsh.tar.gz) einschlagen. Auch andere Scheme-Dialekte sind für das Scripting einsetzbar, die Scsh bietet jedoch die beste Integration in die Unix-Werkzeuge.

Warum soll man für die Shell-Programmierung auf ein Scheme ausweichen? Der Autor der Scheme-Shell, Olin Shivers, stellt dazu fest: “Unix-Shells sind echte Programmiersprachen. Sie besitzen Variablen […]. Aber sie sind schreckliche Programmiersprachen. Die Datenstrukturen bestehen meist nur aus Integers und String-Vektoren. Die Möglichkeiten zur prozeduralen Abstraktion sind minimal bis nicht existent. Die lexikalischen und syntaktischen Strukturen sind mehrfach bestimmt, prinzipienlos und verschnörkelt.” [1]

Die ziemlich harsche Kritik zielt hauptsächlich auf den Programmiersprachen-Aspekt. Außen vor bleiben auch die vielen Funktionen, die das Arbeiten auf der Kommandozeile so komfortabel machen. In diesem Bereich hat die Scsh ihre großen Schwächen. Dass die Shell-Programmierung keine ganz einfache Materie ist, kann man vielleicht an der Länge der Unix-FAQ [3] ermessen.

Umbenennung einer Reihe von Dateien

Die Frage nach der Umbenennung einer Reihe von Dateien findet man auch in Punkt 2.6 der Unix-FAQ. Es handelt sich also um ein nicht triviales Problem, sonst fände es sicherlich nicht seinen Weg in die FAQ. Hier eine Möglichkeit für eine Bourne Shell:

function rename_1 (){
  from=$1
  to=$2
  mv $from $(echo $to | tr `[A-Z]' `[a-z]').html
}
for f in *.HTM; do
  base=`basename $f .HTM`
  rename_1 $f $base
done

Wenden wir das Ganze einmal auf folgende vier Dateien an: T1.HTM, T2.HTM, with blank.HTM und T3.HTM. Es resultiert die Ausgabe: mv: Beim Verschieben mehrerer Dateien muss das letzte Argument ein Verzeichnis sein. Diese Fehlermeldung ist nicht sehr hilfreich. Schauen wir mal nach, wo denn etwas schief gegangen sein könnte. Ein ls zeigt an, dass die Umbenennungen für alle Dateien – bis auf jene mit Leerzeichen – geklappt haben.

Es handelt sich also um ein Problem von Leerzeichen in Dateinamen, den Hinweis auf ein Verzeichnis kann man wohl getrost vergessen. Versuchen wir es also einmal auf eine andere Art:

function rename_2 (){
  from=$1;
  to=$2
  mv $from "$(echo $to | tr `[A-Z]' `[a-z]').html"
}

Folgende Dateien sind da: t1.html, t2.html, with blank.html und t3.html. Der zweite Weg scheint brauchbar. Für Umlaute oder andere ungewöhnliche Namen in Dateinamen müssen Sie aber sehr viel über Quoting, Prozesssubstitution und Sonderzeichen wissen. Nun einmal das Ganze in der Scheme-Shell:

#!/usr/local/bin/scsh -l ./stringhax.scm -s 
!#
(define (rename-them)
  (let ((file-list (glob "*.HTM")))
    (for-each 
      (lambda(x) (rename-file x 
 (replace-extension 
          (downcase-string x) ".html")))
      file-list)))
(rename-them)

Auf die gleichen Dateien angewandt erhalten wir direkt die erwarteten Ergebnisse. Betrachten wir den Aufbau eines Scsh-Skripts: Wie bei jedem Skript wird in der ersten Zeile angegeben, durch welches Programm dieses Skript bearbeitet werden soll. Die nachfolgenden Zeilen sind Kommandozeilen-Argumente für die Scsh, aufgeführt sind sie in Kapitel 2 aus [2], Seite 161.

Im Beispiel wird zunächst die Datei stringhax.scm geladen, in der man einige Erweiterungen für die Behandlung von Zeichenketten findet; benötigt wird nur die Funktion downcase-string. Das -s begrenzt die erweiterte Kommandozeile und muss immer die letzte Option vor !# sein.

Im Folgenden wird eine Funktion rename-them definiert. glob pattern erzeugt eine Liste, deren Elemente pattern entsprechen. Daraufhin wird in einer Schleife jede Datei aus der Liste einzeln umbenannt. Das erfordert gleich mehrere Funktionen: Eine benennt die Dateien um, eine weitere ersetzt die Erweiterung und die dritte benennt die Dateinamen in Kleinbuchstaben um. Der Aufruf der gerade definierten Funktion beschließt das Skript.

Listing 1: Ausnahmebehandlung in der Scsh

(define (error-handling-test)
  (let ((dir "dir"))
    (create-directory "dir")
    (with-errno-handler
     ((e1 d1)
      ((errno/exist)
       (format #t "errno-msg = ~A~%
     syscall = ~A~%data = ~A~%~%
                   Directory exists~%"
               (nth d1 0) (nth d1 1) (nth d1 2)))
      (else (error "Do not know that to do now, giving upn")))
     (create-directory dir))
    (with-errno-handler
     ((e2 d2)
      ((errno/isdir) 
       (display "Ups, was a directory
                 so running delete-directory insteadn")
       (delete-directory dir)))
     (delete-file dir))))

Listing 2: Awk auf Scheme-Art

#!/usr/local/bin/scsh -s
!#
;;; Add the numbers of kb of free and used disk space for all the volumes
;;; reported by df(1)
(define (df-free+used)
  (let ((df-read (field-reader))) ;df 1
    (exec-epf 
     (| (df) ;df 2 
        (begin 
          (read-line) ; skip first line of df ;df 3
          (awk (df-read) (line fields) ;df 4
               ((used-kb 0) (free-kb 0)) ;df 5
               (#t  ;df 6
                 (values (+ used-kb (string->number (nth fields 2)))
                         (+ free-kb (string->number (nth fields 3)))))
               (after
                (values `(`used-mb ,(/ used-kb 1024.0)) ;df 7
                        `(`free-mb ,(/ free-kb 1024.0))))))))))
(receive 
 (used-list free-list) 
 (df-free+used) ; df 8
 (format #t "Es sind ~A MB belegt und noch ~A MB frei.~%"
         (cadr used-list)
         (cadr free-list)))

Das Umwandeln von Umlauten funktioniert aber auch in der Scheme-Shell nicht! In den Quellen zu diesem Artikel habe ich daher eine weitere Funktion definiert, die auch die Umlaute korrekt ersetzt [7].

Merkmale der Scheme-Shell

Vielleicht konnte Sie das Beispiel davon überzeugen, dass man mit einer vollwertigen Programmiersprache die Shell-Programmierung vereinfachen kann. Für die Verbindung mit dem zugrunde liegenden System bietet die Scsh

  • Mechanismen, um die Daten der Unix-Programme und der Shell zu integrieren, sowie
  • eine in Scsh umgesetzte Posix-API.

Prozesskontrolle

Normalerweise wird in Unix jedes gestartete Programm zu einem eigenen Prozess. Oft bestehen Shell-Programme aus einer Kombination mehrerer Programme, die zum Beispiel durch Pipes verbunden werden. Die Scsh benötigt also Kanäle, um die Programme verbinden zu können. Hier ein einfaches Beispiel:

(define (example-1-copy from to)
 (run (cat ,@from)
       (> ,to)))

Die Funktion erwartet eine Liste von Dateien, die mit cat aneinander gehängt und nach to geschrieben werden. Für run wie auch weitere Elemente zur Prozesskontrolle gilt, dass die Formen implizit gebackquoted sind. Liegt zum Beispiel eine Datei t1.txt vor, können Sie auf folgende drei Arten darauf zugreifen:

* (run (cat "t1.txt"))
* (run (cat t1.txt))
* (define file "t1.txt") (run (cat ,file))

In der Scsh spielt die Groß- und Kleinschreibung im Gegensatz zu Standard-Scheme eine Rolle, da Unices von Hause aus zwischen Groß- und Kleinschreibung unterscheiden. Damit sich die Scsh möglichst gut in dieses Schema einfügt, scheint diese Erweiterung angebracht. Ein Mechanismus wie run ist für die Integration nicht ausreichend, weshalb weitere Funktionen zur Prozesskontrolle wie Funktionen zur Ein- und Ausgabeumlenkung, Jobkontrolle und Pipes bereitstehen. Beispiel für eine Pipe mit der Scsh:

(run (|(cat foo bar)
       (grep -n "<foo>"))        
     (> foo_lines))

Weitere Elemente finden Sie in [2].

Datenaustausch zwischen Dienstprogrammen und Scheme

Wer auf alle Unix-Programme zugreifen will, braucht Möglichkeiten, Daten von den Dienstprogrammen der Scheme-Shell verfügbar zu machen. Dazu dienen die run/xxx-Funktionen. Möchte man beispielsweise eine Liste der Dateien im aktuellen Verzeichnis haben, dann gibt man (run/strings (ls)) ein. Das Ergebnis ist eine Liste von Zeichenketten mit dem Namen der Dateien, die mit allen Elementen der Scheme-Programmierung weiterverarbeitet werden kann.

Andere run/xxx Befehle dienen dazu, etwa auf Ports oder in temporäre Dateien zu schreiben oder die Ausgabe in eine einzelne Zeichenkette umzuwandeln. So erhalten Sie mit der Anweisung (run/string (cat foo bar)) eine Zeichenkette, die aus allen Zeilen der beiden Dateien besteht.

Ein interessantes Beispiel für Linux ist der Befehl run/port+proc, der zusätzliche Informationen des geforkten Prozesses, zum Beispiel Ausgabestatus, aktueller Status und Weiteres, zurückliefert.

(define (run/port+proc-test)
  (receive (port process) (run/port+proc (ls -l)) 
  (let ((out (port->string port)) 
    (exit-status (wait process)))
    (display "the pid of the process was ")
    (display (proc:pid process))
    (display ", exit status = ")
    (display exit-status)
    (newline)
  out)))

Die Scsh bindet mit der Form receive mehrere Rückgabewerte. Die zu bindenden Parameter befinden sich in der ersten Liste (hier port und process), anschließend wird die Funktion aufgerufen, die diese Werte liefert ( run/port+proc).

Im Beispiel wird die Ausgabe von ls -l auf den Port geschrieben, mit port->string diese Ausgabe in eine Zeichenkette umgewandelt, die am Ende den Rückgabewert dieser Funktion bildet. Der Ausgabestatus des mit run /port+proc gestarteten Programms wird in exit-status festgehalten. proc:pid greift auf das Element pid der proc Struktur zu. Das handhabt die Scsh also auf andere Art als DrScheme.

Ausnahmen

Die Scheme-Shell verpackt prinzipiell alle Posix-Systemaufrufe in einer Scheme-Syntax. Falls Fehler auftreten, werden Ausnahmen erhoben, die man bearbeiten kann (siehe Listing 1). Die Ausnahmebehandlung wird wie folgt abgearbeitet: Der Rumpf der Ausnahme wird zunächst ausgeführt, also in der ersten Fehlerbehandlungsroutine die Funktion create-directory, in der zweiten delete-file.

Sollte eine Ausnahme auftreten, wird der erste Parameter der Fehlerbehandlungsform e1 an den Wert von errno gebunden, der zweite Parameter e2 an eine Liste. Letztere besteht aus einer Fehlermeldung, die der Ausgabe von perror errno entspricht, der fehlgeschlagenen Systemfunktion (diesen Parameter kann man dazu nutzen, die fehlgeschlagene Methode nochmals aufzurufen) sowie weiteren Informationen, die je nach Systemfunktion unterschiedlich ausfallen.

Danach werden die einzelnen Fälle für die Fehlerbehandlung der Reihe nach untersucht, der erste zutreffende Fall wird ausgeführt, wobei der Rückgabewert des ausgeführten Zweigs zum Wert der gesamten Fehlerbehebung wird.

Im Beispiel wird kein Verzeichnis angelegt und eine Fehlermeldung ausgegeben, falls ein Verzeichnis gleichen Namens schon existiert. Ließ sich im zweiten Teil das Verzeichnis nicht löschen, wird eine ungeeignete Funktion delete-file aufgerufen, die zwangsläufig einen Ausnahmefehler erzeugt. Zur Korrektur wird dann die richtige Löschfunktion delete-directory aufgerufen.

Systemaufrufe und weitere Funktionen

Die Scsh bietet weitaus mehr Funktionen für die verschiedensten Bereiche, die hier nur kurz aufgezählt werden sollen:

  • Ein-/Ausgabe (Scheme-Standardfunktionen und Ergänzungen)
  • File/Directory-Bearbeitung und -Information
  • Globbing
  • Weitere Elemente zur Prozesskontrolle
  • Signale und Unterbrechungen
  • Funktionen zur Behandlung von Zeiten
  • Umgebungsvariablen
  • Terminal-Kontrolle
  • Reguläre Ausdrücke
  • Netzwerkprogrammierung
  • Bitmanipulationen

Besonders interessant ist die Umsetzung so genannter kleiner Sprachen in die Scheme-Syntax, zum Beispiel das awk-Makro der Scsh. Im Beispiel (siehe Listing 2) wird der gesamte belegte und freie Platz der Festplatte ermittelt. Für einzelne Partitionen könnte man dazu auch df einsetzen, jedoch gibt es kein Dienstprogramm, das den gesamten freien und belegten Platz der Festplatte anzeigt.

Die Rückgabe in Form von Scheme-Ausdrücken ( ; df 7) folgt einer Empfehlung Olin Shivers. Er bemerkte dazu, dass sich auf diese Art die Daten einfacher in anderen Funktionen weiterverarbeiten lassen, da man sich der Funktionalität von read bedienen kann.

Listing 3: Anlegen einer bunten Tabelle

(load (string-append laml-dir "laml.scm"))
(laml-style "simple-html4.0-loose")
(generic-page-1
  "Eine Seite mit einer ganz bunten Tabelle"
  (con-par 
     "Diese Seite zeigt einige der Elemente aus der 
      HTML 4.0 convenience Bibliothek"
     (em "Hervorhebungen sind kein Problem"
         (b "auch fett") "funktioniert.")
     
     "Hier noch eine bunte Tabelle, bitte Augen auf ;-)"
     (table-1
       2 ; border 
       (list 70 100 100 100) ; vier Spalten
       (list (make-color 106 90 205)
             (make-color 0 255 255)
             (make-color 127 255 212)
             (make-color 238 121 159)) ; "wunderbare" Farben;
       (list 
        (list "Hier" "eine" "Tabelle" "mit")
        (list "den" "geschmackvollsten" "Farben" "ein")
        (list "Werk" "von" "bleibendem" "Wert")) ; Text in Tabelle
       "middle")
  
     (b "Hier beenden wir diese `nette' Seite aber nicht ohne")
     (con "auf ein anderes `Meisterwerk' zu verweisen " 
          (a-tag "simple.html" "simple")))  ; ein Link
  
  ;; Farben für diese Seite 
  (make-color 255 255 191) (make-color 205 105 201) blue red
  )

(end-laml)
Abb. 1: Eine von LAML erzeugte Tabelle.

Abb. 1: Eine von LAML erzeugte Tabelle.

Untersuchen wir das Programm etwas genauer: Die Ausgabe von df unterliegt einem konsistenten Format Filesystem Gesamtgröße BenutzteBytes FreieBytes ..n. Es handelt sich um mehrere Felder, die durch Leerzeichen voneinander getrennt sind. Das Einlesen von Zeilen ist in der Scheme-Shell von der Bearbeitung der aktuellen Zeile getrennt worden. Das Einlesen erfolgt durch so genannte Feldleser (Field Reader) ( ; df 1). Die Ausgabe von df wird nach Scheme gepiped ( ; df 2). Da die erste Zeile der Ausgabe von df Text enthält, der für die Berechnung der Kapazitäten unwichtig ist, wird sie einfach überlesen ( ; df 3).

Der Field Reader von Scsh liefert zwei Werte zurück: die vollständige Zeile und dazu eine Liste mit einzelnen Elementen. Die Zeilen werden durch bestimmte Feldtrenner in Wörter zerlegt. Wenn keine besonderen Zeichen angegeben sind, gelten Whitespaces als Trenner. Wir definieren zwei Variablen ( ; df 5), die die Summe der benutzten und der freien KBytes enthalten werden.

Für das weitere Verständnis von awk muss man sich die Arbeitsweise des Original- awk etwa so vorstellen: Um ein awk-Skript liegt eine Schleife, die Dateien Zeile für Zeile einliest (oder je nach Feldtrenner auch mehrere Zeilen). In awk-Skripten liegt dann zusätzlich eine implizite Fallunterscheidung zugrunde, in der die aktuelle Zeile mit regulären Ausdrücken verglichen wird.

Im Scsh-Pendant zu awk lassen sich weitere Elemente einsetzen: boolsche Werte, reguläre Ausdrücke und Scheme-Ausdrücke. In unserem Fall sind wir an allen Zeilen interessiert, da in jeder Zeile die benutzten und freien Bytes des jeweiligen Dateisystems aufgelistet werden. Daher benutzen wir als Test einfach #t ( ; df 6), das passt auf jede einzelne Zeile.

Scheme-Server und -Client

Client

(define (send-to-server form)
 (let* ((sock (socket-connect 
       protocol-family/internet
       socket-type/stream
       "localhost" test-port))
 (op (socket:outport sock)))
   (format #t "I'll send ~A~%" form)
   (cond 
    ((number? form)
     (write (number->string form) op))
    (else
     (write form op)))
   (force-output op)
   ;(sleep 1)a
   (let ((result (read (socket:inport sock))))
     (format #t "I got ~A from the Server~%" result)
     (force-output (current-output-port)))
   (close-socket sock)))

Server

(define test-port 1111) ;sk 1
(define (scheme-server)
  (let* ((log-file-name "./scheme-server.log") ;sk2
         (log-file (open-output-file 
                    log-file-name 
                    (bitwise-ior open/append open/create)))) ;sk2
    (bind-listen-accept-loop 
     protocol-family/internet
     (lambda (sock addr)
       (let* ((op (socket:outport sock))
              (input (read (socket:inport sock))))
         (format log-file "Got:  ~A~%" input) ;sk 2
         (force-output log-file)
         (let ((output (eval input (interaction-environment))))
           (format log-file "Wrote: ~A~%" output) ;sk 2
           (force-output log-file) 
           (cond 
            ((number? output)
             (write (number->string output) op))
            (else
             (write output op)))
           (force-output op))))
     test-port)))

Der Server wartet in diesem Beispiel am Port 1111 (; sk1) auf Anfragen. Eine Fehlerbehandlung wurde nicht vorgesehen, jedoch wird der gesamte Datenaustausch geloggt (; sk2). Die Funktion bind-listen-accept-loop ist ein Wrapper um Basisfunktionen wie create-socket, connect-socket, bind-socket und weitere. Für die Ausgabe auf Sockets stehen Erweiterungen wie receive-message und send-message bereit; oder Sie nutzen einfach die Scheme-Standardfunktionen wie in unserem Fall read und write.

Ein paar Anwendungsbeispiele:

(send-to-server "foo") -> I got foo from the Server
(sent-to-server `(+ 1 2)) -> I got 3 from the Server
(send-to-server `(map (lambda (x) (+ 1 x)) `(1 2 3))) 
 -> I got (2 3 4) from the Server

Für jede eingelesene Zeile werden die lokalen Variablen angepasst; zu used-kb wird das dritte Element der Liste addiert, das entspricht fast immer den benutzten KBytes auf dem gerade untersuchten Dateisystem. Analog wird mit free-kb und dem vierten Listenelement verfahren.

Zum Abschluss werden die KBytes noch in MBytes umgerechnet ( ; df 7) und zwei Rückgabewerte in der Form (Symbol ,(errechnete MBytes)) zurückgegeben. Der Aufruf der gerade definierten Funktion ( ; df 8) bildet den Abschluss dieses Skripts. Als Ausgabe erhalte ich auf meinem Rechner:

Es sind 3976.94 MB belegt und noch 2885.82 MB frei

Es bleibt also erfreulicherweise noch ein wenig Platz für weitere Artikel übrig. ;-)

Da das Zusammenspiel der Funktionen zum Einlesen der Zeilen und der Bearbeitung durch das awk-Makro auf den ersten Blick ziemlich verwirrend ist, möchte ich Sie auf das Kapitel 8 aus [2] verweisen. Dort finden Sie eine ausführliche Dokumentation zu diesem Thema.

Netzwerkprogrammierung

Auch dafür bietet die Scsh einige Funktionen. Man kann sie in die Kategorien Basisfunktionen und darauf aufbauende Bequemlichkeitsfunktionen einteilen. Mit den Letzteren lässt sich ziemlich einfach ein Scheme-Server erstellen (siehe Kasten “Scheme-Server und -Client”). Es handelt sich tatsächlich um einen Scheme-Server in nicht mehr als 22 Programmzeilen.

Scheme und Internet

Funktionale oder deklarative Sprachen wie Scheme bieten sich für die Nutzung der heutigen Internet-Dienste geradezu an. Die Basiselemente haben Sie im vorherigen Beispiel kennen gelernt, darauf aufbauend haben Scheme-Liebhaber aber noch eine ganze Reihe weiterer Dienste implementiert. Beispielsweise einen HTTP-Server sowie Funktionen für die Mail-Behandlung, Module für HTML-formatierte Ausgaben und CGI-Programmierung.

In der DrScheme-net-Sammlung [6] finden sich weitere Dienstprogramme für SMTP, NNTP, DNS, POP3 und IMAP. Sie brauchen also auch für solche speziellen Programme nicht auf andere Skriptsprachen auszuweichen.

Scheme als Markup-Sprache

Das prominenteste Beispiel einer Markup-Sprache ist derzeit HTML. Der Begriff Sprache ist jedoch irreführend, da es sich bei HTML nicht um eine echte Programmiersprache handelt, sondern um ein Hilfsmittel zur Beschreibung von Seiten. Für weiterführende Elemente, zum Beispiel Schleifen und Fallunterscheidungen, muss man auf echte Programmiersprachen ausweichen.

Wie wäre es nun, wenn man zu einer Programmiersprache Markup-Elemente hinzufügen würde? Genau das dachte sich auch Kurt N¿rmark und entwickelte LAML (Lisp Abstracted Markup Language). LAML ist in verschiedene Schichten gegliedert – auf der untersten stehen einfach nur Wrapper um die unterschiedlichen HTML-Auszeichnungen. Wie die Schichten im Einzelnen aufgebaut sind, können Sie in der recht ausführlichen Dokumentation von LAML nachlesen ([5]).

Erste Schritte in LAML

(load (string-append laml-dir "laml.scm"))
(laml-style "simple")
(generic-page-1
  "Grüsse von LAML"
  "Extra für Sie eines der beeindruckendsten Meisterwerke
   LAMLischer Programmierkunst ;-)")
(end-laml)

Hier ein erstes LAML-Beispiel: LAML-Dateien werden mit einer geeigneten Scheme-Implementierungen nach HTML übersetzt, wobei derzeit MzScheme das Entwicklungs-Scheme für LAMLs ist. Auf welche Weise Sie die Dateien übersetzen, hängt von der Umgebung, in der Sie arbeiten, ab. So gibt es einen laml-mode für den (X)Emacs, mit dem Sie die Übersetzung von LAML-Dateien direkt vom Editor aus starten können. Alternativ ruft man das LAML-Skript auf (dabei handelt es sich um ein MzScheme-Skript) oder man lädt die entsprechenden Dateien in ein Scheme und ruft die LAML-Funktion auf (laml “Datei.laml”). Ein weiteres Beispiel für den Gebrauch von LAML findet sich in Listing 3. Sie stimmen sicherlich mit mir darin überein, dass die Farbauswahl der Tabelle (Abbildung 1) dem Auge schmeichelt.

Abb. 2: LAML in der Praxis - Vorlage für eine Vorlesung.

Abb. 2: LAML in der Praxis – Vorlage für eine Vorlesung.

Zusammenfassung

In diesem Teil wurde Scheme als Scripting- und Markup-Sprache vorgestellt. Die Anwendungsbeispiele zeigen, wie flexibel Scheme eingesetzt werden kann. Wer sich mit Scheme auskennt, hat ein Werkzeug zur Verfügung, das eine ganze Reihe anderer ersetzen kann.

Die nahtlose Umsetzung der verschiedenen Elemente ist sicherlich ein weiterer Vorteil von Scheme. Sie können immer auf die volle Funktionalität einer Programmiersprache zurückgreifen, es bestehen praktisch keine Beschränkungen, denen Sie bei anderen Programmen unterliegen können. Ich denke, das sind ein paar gute Gründen für das Erlernen von Scheme.

Ausblick

Im letzten Teil über Scheme steht weiterhin das Internet im Mittelpunkt. Wir werden Scheme auch für die CGI-Programmierung und außerdem in Verbindung mit Java einsetzen. So gibt es Schemes, die speziell für die Interaktion mit Java entwickelt wurden und Ihnen den nahtlosen Zugriff auf Java-Klassen erlauben.

Wie immer würde ich mich über Rückmeldungen und Anregungen zu diesen Beiträgen freuen. ( tfr)

Infos

[1] “A Scheme Shell”, Olin Shivers, SCSH Paper (kommt mit den Sourcen)

[2] “Scsh Reference Manual”, Olin Shivers (ebenfalls bei den Sourcen)

[3] Unix-FAQ: ftp://rtfm.mit.edu/pub/usenet-by-hierarchy/comp/unix/answers/unix-faq/

[4] SCSH-Homepage: http://www-swiss.ai.mit.edu/ftpdir/scsh/

[5] LAML-Homepage: http://www.cs.auc.dk/~normark/laml/

[6] DrScheme net collection im DrScheme-Rootverzeichnis /collect/net

[7] Rename-Funktion: ftp://ftp.linux-magazin.de/pub/listings/2001/04/Scheme/rename-1.scm

LINUX-MAGAZIN KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Readly Logo
E-Mail Benachrichtigung
Benachrichtige mich zu:
0 Kommentare
Älteste
Neuste Beste Bewertung
Inline Feedbacks
Alle Kommentare anzeigen
Nach oben