Zum Inhalt springen

Tcl

aus Wikipedia, der freien Enzyklopädie
Dies ist eine alte Version dieser Seite, zuletzt bearbeitet am 17. Dezember 2004 um 10:01 Uhr durch Suchenwi (Diskussion | Beiträge) (Beispielprogramme: Fakultät). Sie kann sich erheblich von der aktuellen Version unterscheiden.

Tcl (ursprünglich "Tool command language", also etwa "Werkzeugsprache") ist eine OpenSource - Skriptsprache, die sehr einfach zu erlernen ist und mit der Applikationen innerhalb kurzer Zeit erstellt werden können. Tcl wird üblicherweise wie engl. tickle (kitzeln) ausgesprochen oder natürlich Te Ce El. Sie ist mit Unix-Shell-Sprachen verwandt. Die Syntax sieht C-ähnlich aus, aber auch starke Bezüge zu Lisp sind vorhanden.

Sehr bekannt ist Tcl durch das Tk Toolkit, mit dem sich portable grafische Benutzeroberflächen leicht programmieren lassen. Der grafische Werkzeugkasten "Tk" steht für eine Vielzahl von Betriebssystemen mit dem für die jeweiligen Fensterverwalter üblichen Aussehen ("native look and feel") zur Verfügung. Diese Programmierschnittstelle wird auch von Perl und Python benutzt. Die Kombination aus Sprache und Toolkit, auch bekannt als Tcl/Tk, ist jedoch besonders einfach zu verwenden; sie stammt von John Ousterhout (seit 1988). Tcl arbeitet standardmässig mit Unicode, so dass Zeichenketten ohne besonderen Aufwand alle Zeichen bis U+FFFD enthalten können. Über 16 bit hinausgehende Unicodes werden noch nicht unterstützt.

Syntax

Tcl ist im Grundsatz sehr einfach aufgebaut und grenzt sich gegen Sprachen wie Perl, APL und C durch absolut konsequenten Einsatz einer einheitlichen Syntax ab. Wer mit Kommandozeileninterpretern (Shell, MS-DOS) vertraut ist, kennt auch die Grundstruktur von Tcl-Kommandos. Ein Tcl-Skipt besteht aus mehreren Kommandos. Ein Kommando besteht aus einem Kommandowort gefolgt von Argumenten (Parameter). Ein Kommando wird von einem Zeilenende oder Semikolon begrenzt. Gegenüber einfachen Kommandozeileninterpretern verfügt aber Tcl über die Möglichkeit, Kommandos ineinander zu verschachteln. Statt eines Argumentes in einem Kommando, kann in eckigen Klammern ein weiteres Kommando angegeben werden. Die Unterkommandos werden zuerst ausgeführt. Ihr Resultat wird dann jeweils als Argument im übergeordneten Kommando eingesetzt.

Auch Konstrukte wie if und while, über Zuweisungen bis hin zu Kommentaren sind Kommandos. Der Kommentar ist ein Kommando, das einfach nichts tut. Die Kommandos folgen der Polnischen Notation, wie Lisp. Das Kommandowort steht am Anfang, dann folgen die Parameter.

 kommandoWort par1 par2 ..parN

Ein Rückstrich (Backslash) am Ende einer Zeile markiert, dass ein Kommando auf der nächsten Zeile fortgesetzt wird.Anführungsstriche schliessen Zeichenketten ein. Damit keine Verwechslungen auftreten, sind einfache Anführungen (Hochkommata) unbekannt. Auch das einfache Gleichheitszeichen (=) kommt nicht vor. Das doppelte Gleichheitszeichen dient Vergleichen.

Geschweifte Klammern schützen ihren Inhalt von Interpretation. Dadurch können Kommandos dann auch mehrere (auch viele) Zeilen umfassen. Als Beispiel sei das While-Kommando erwähnt. Es erwartet zwei Argumente, das erste enthält einen Befehl, der die Bedingung repräsentiert, das zweite die auszuführenden Kommandos innerhalb der While-Schleife.

while { einTclKommando }  { 
        FolgeVonTclKommandos
   }                       

Die geschweiften Klammern schützen den Inhalt vor der Interpretation *vor* dessen Übergabe an den While-Befehl. Innerhalb des While-Befehls werden sie so wie nötig evaluiert.

If-Anweisung:

 if { Bedingung }  {
      FolgeVonTclKommandos
    }

Zuweisungen geschehen mit dem Kommando set - ohne ein Gleichheitszeichen. So ist auch hier kein Bruch in der extrem einfachen Syntax vorhanden:

  set variable value

Weiter gibt es ein leistungsfähiges switch-Kommando, ein For- und ein Foreach-Kommando. Vor allem letzteres ist deutlich mächtiger als Iterationen in anderen Sprachen. Beispiel, um aus einer Liste von x/y-Koordinaten und einer weiteren aus z-Koordinaten eine Liste aus x/y/z-Koordinaten zu erstellen:

set xyzlist {}
foreach {x y} $xylist z $zlist {lappend xyzlist [list $x $y $z]}

Es können also mehr als ein Element aus einer Liste, sowie Elemente aus mehreren Listen in einem Schleifendurchlauf verwendet werden.

Ein Kommando liefert einen Stringwert oder eine Liste als Resultat zurück.

glob aPattern

erzeugt eine Liste der Dateinamen im Arbeitsverzeichnis, deren Namen mit aPattern übereinstimmen. Pattern können ? (ein beliebiges Zeichen), * (0 oder mehr beliebige Zeichen) oder Klassen von Zeichen in eckigen Klammern enthalten. Dann aber sind letztere mit geschweiften Klammern vor zu früher Auswertung zu schützen:

glob {[abc]?-*.tcl}

liefert Datei- oder Verzeichnisnamen, die mit a, b oder c beginnen, danach aus einem beliebigen Zeichen und einem Bindestrich, danach einer beliebigen (auch leeren) Zeichenfolge und schließlich ".tcl" bestehen.

Arithmetische Ausdrücke werden durch das Kommando expr ausgeführt.

 set res [expr 4 + 2 * 3]
 puts $res

ergibt 10. Die Dynamik der Datentypen erlaubt einfache Codierung wie diese:

proc Quersumme Zahl {expr [join [split $Zahl ""] +]}
* [split $Zahl ""] zerlegt die Zahl in Ziffern: 4711 -> 4 7 1 1
* [join ... +] fügt zwischen je zwei Ziffern ein "+"-Zeichen ein
* [expr ...] berechnet schließlich den so entstandenen Ausdruck.

Datentypen

Tcl ist eine typlose Sprache. Jede Variable enthält Zeichenketten. Intern wird dann aber schon zwischen den Grund-Datentypen Ganzzahl, Fließkommazahl und Zeichenkette unterschieden. Die Verwendung einer nicht definierten Variable führt allerdings zu einem Fehler - im Gegensatz zur Programmierung mit dem Unix-Kommandozeileninterpreter oder awk. Konstrukte wie assoziative Arrays (Hashtabelle) und Listen werden in Tcl oft angewendet.

Das folgende Programmschnipsel deklariert implizit einen assoziativen Array und füllt ihn mit Werten.

set hauptstadt(Frankreich)  Paris
set hauptstadt(Italien)     Rom
set hauptstadt(Deutschland) Berlin
set hauptstadt(Polen)       Warschau
set hauptstadt(Russland)    Moskau
set hauptstadt(Spanien)     Madrid

Alternativ ist folgende Schreibweise möglich, und oft kompakter:

array set hauptstadt {
   Frankreich Paris  Italien Rom  Deutschland Berlin .. ..
}

Ein bestimmter Wert kann wie folgt auf das Ausgabemedium geschrieben werden

puts $hauptstadt(Italien)

Eine Liste von allen Ländern zu denen Hauptstädte angegeben worden sind erzeugt der folgende Tcl-Befehl

array names hauptstadt

Der Tcl-Interpreter antwortet mit z.B.

Polen Spanien Russland Deutschland Italien Frankreich

Die Liste ist nicht sortiert. Die Liste wird sortiert ausgegeben mit:

lsort [array names hauptstadt]

Bearbeitung von Zeichenketten

Tcl kennt sehr leistungsfähige Kommandos zur Bearbeitung von (auch langen) Zeichenketten - mindestens ebenbürtig denen von Perl und Python, ebenso Dateibearbeitung, TCP/IP-Netzkommunikation und über Tk grafische Programmierung und ist in all diesem völlig plattformunabhängig. Tcl hat einen Mechanismus eingebaut, um mit Regulären Ausdrücken arbeiten zu können.

Einsatzbereiche

Tcl wird übrigens nicht nur auf der Kommandozeile, sondern auch als embedded language, als CGI-Sprache (wie sonst oft Perl) und als Modul im Apache-Webserver (wie sonst oft PHP) eingesetzt. Sie ist über eine einfache Schnittstelle zu C leicht erweiterbar.

Beispielprogramme

Fakultät

proc ! x {expr {$x<2? 1: $x*[! [incr x -1]]}}

Dies ist ein Beispiel für sehr kompakten, funktionalen Programmierstil. Es zeigt, daß beliebige Strings (hier "!") Namen von Funktionen sein können; daß innerhalb des expr-Kommandos auch der ternäre x?y:z-Operator wie aus C bekannt verfügbar ist; daß aber Tcl-Funktionen durchaus ganz anders als C-Programme aussehen können.

Digitaluhr

Hier ein kleines Beispielprogramm in Tcl/Tk, eine Digitaluhr in 6 Zeilen (Quelle: The Tcl'ers wiki - A simple A/D clock):

proc every {ms body} {
    eval $body
    after $ms [list every $ms $body]
}
pack [label .clock -textvar time]
every 1000 {set ::time [clock format [clock sec] -format %H:%M:%S]}

In den ersten vier Zeilen wird ein Zeitgeber (Timer) angelegt, der ein Skript "body" regelmäßig alle "ms" Millisekunden ausführt (indem er sich selbst zum Wiederaufruf vormerken lässt). In der fünften Zeile wird ein Label in einem Fenster auf dem Bildschirm angelegt und mit einer Variablen "time" verbunden. In der sechsten Zeile wird der Timer "every" aufgerufen, um jede Sekunde die Variable "time" auf die aktuelle Uhrzeit im Format Stunde-Minute-Sekunde zu setzen. Fertig ist ein komplettes Programm mit GUI.

Arraydaten abfragen

Im Array tcl_platform liegen Angaben zur Plattform vor auf der der Tcl-Interpreter läuft. Das folgende Code-Stück gibt sie auf dem Standard-Ausgabemedium aus:

 foreach i [array names tcl_platform] {
    puts [ concat $i= $tcl_platform($i) ]
 }

Eine hübschere Variante (alphabetisch sortiert, bündige Gleichheitszeichen) ist

parray tcl_platform

Minimaler Editor

Der folgende Code definiert einen kompletten minimalen Editor; er stammt von Richard Suchenwirth [1]; detaillierte Erklärungen unter [2]

# Hilfetext definieren
set about "minEd - a minimal editor
Richard Suchenwirth 2003
F1: help
F2: load
F3: save
"
# GUI definieren, drei F-Tasten rufen Prozeduren auf
pack [scrollbar .y -command ".t yview"] -side right -fill y
pack [text .t -wrap word -yscrollc ".y set"] -side right -fill both -expand 1
bind . <F1> {tk_messageBox -message $about}
bind . <F2> {loadText .t [tk_getOpenFile]}
bind . <F3> {saveText .t [tk_getSaveFile]}
proc loadText {w fn} {
   if {$fn==""} return
   wm title . [file tail $fn]
   set fp [open $fn]
   $w delete 1.0 end
   $w insert end [read $fp]
   close $fp
}
proc saveText {w fn} {
   if {$fn==""} return
   set fp [open $fn w]
   puts -nonewline $fp [$w get 1.0 "end - 1 c"]
   close $fp
}
# Falls Editor mit Angabe einer Datei aufgerufen wurde, diese öffnen.
if {$argc > 0} {loadText .t [lindex $argv 0]}

HTML-Seite herunterladen

Das http-Package enthält Befehle um mit dem http-Protokoll zu arbeiten. Die folgenden Codezeilen laden eine HTML-Seite herunter.

package require http
 puts [http::data [http::geturl http://mini.net/tcl/540]]

Erweiterungen

XOTcl ist eine objektorientierte Erweiterung. Sie unterstützt auch Metaklassen. Definitionen von Klassen und Methoden sind vollständig dynamisch änderbar.


Aufruf

Tcl ist in den meisten Unixinstallationen bereits voreinstalliert. Mit

  tclsh

wird es aufgerufen. Wenn man auch das grafische Toolkit dabeihaben will, ist

  wish

aufzurufen. (Seit Tcl 8.4 reicht die tclsh in allen Fällen aus, sofern interaktiv oder im Script

package require Tk

eingegeben wird.)

  expect

enthält auch Tcl und ist speziell darauf ausgerichtet bestehende Kommandozeilen-Unix-Programme, die kein GUI haben mit einer Oberfläche zu versehen.

Für andere Betriebssysteme bestehen auch verschiedene Installationspakete. Interessant ist auch das TclKit, das für Windows aus einer einzigen weniger als 1MB grossen Datei besteht. Durch einfaches Kopieren dieser Datei wird Tcl mit Tk verfügbar gemacht. Eine Applikation, die gerne aus vielen Dateien bestehen kann, wird in einem Starkit (eine Datei) komprimiert und zusammengepackt, und ist plattformunabhängig lauffähig, sofern ein Tclkit vorhanden ist. Die Kombination aus einem Starkit und einem Tclkit in einem einzigen File wird "Starpack" genannt - sie erlaubt, eine Applikation in einer einzigen Datei (dann allerdings plattformspezifisch) auszuliefern.

Der Java-Wahlspruch write once - run anywhere wird hier Wahrheit; zumindest auf den Plattformen Unix (diverse), Windows (95..NT..XP..CE) und Mac.

Siehe auch