1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
|
---
language: Tcl
contributors:
- ["Poor Yorick", "http://pooryorick.com/"]
translators:
- ["Martin Schimandl", "https://github.com/Git-Jiro"]
filename: learntcl-de.tcl
lang: de-de
---
Tcl wurde kreiert von [John Ousterhout](http://wiki.tcl.tk/John Ousterout) als
eine wiederverwendbare Scriptsprache für Chip-Design Werkzeuge die er kreiert
hat. Im Jahre 1997 wurde er mit dem [ACM Software System
Award](http://en.wikipedia.org/wiki/ACM_Software_System_Award) für Tcl
ausgezeichnet. Tcl kann sowohl als eingebettete Scriptsprache als auch als
allgemeine Programmier-Sprache verwendet werden. Tcl kann auch als portable
C-Bibliothek verwendet werden. Sogar in Fällen in denen die Script-Fähigkeiten
nicht nötig sind. Denn Tcl stellt Daten-Strukturen wie dynamische Zeichenketten,
Listen und Hash-Tabellen bereit. Die C-Bibliothek stellt auch portable
Funktionen zur Verfügung: Laden von dynamischen Bibliotheken, Zeichenketten
formatierung und Code Konversion, Dateisystem Operationen, Netzwerk Operationen
und mehr.
Verschiedenste herausragende Fähigkeiten von Tcl:
* Praktische Cross-Platform Netzwerk-API
* Vollständig virtualisiertes Dateisystem
* Stapelbare I/O Kanäle
* Asynchron bis zum Kern
* Vollständige Ko-Routinen
* Robustes und einfach zu verwendendes Thread-Modell
Wenn Lisp ein Listen-Prozessor ist, dann ist TCl ein Zeichenketten-Prozessor.
Alle Werte sind Zeichenketten. Eine Liste ist ein Zeichenketten-Format. Eine
Prozedur-Definition ist ein Zeichenketten-Format. Um leistungsfähig zu sein,
werden Tcl-intern diese Zeichenketten in Strukutierter-Form gepuffert. Ein
Beispiel: Der "list" Befehl arbeitet mit diesen internen gepufferten
Repräsentationen. Tcl kümmert sich selbständig darum die String-Repräsentationen
zu aktualisieren, falls dies im Skript benötigt werden sollten. Das Kopieren-
beim-Schreiben-Design von Tcl erlaubt es Skript-Authoren mit großen Daten-
Strukturen zu arbeiten ohne zusätzlichen Speicher-Overhead. Prozeduren werden
automatisch byte-kompiliert außer sie verwenden dynamische Befehle wie zum
Beispiel "uplevel", "upvar und "trace".
Es ist eine Freude in Tcl zu programmieren. Hacker-Typen werden gefallen daran
finden, wenn sie Lisp, Forth oder Smalltalk interessant finden. Tcl wird auch
Ingenieuren und Wissenschaftlern gefallen die nur den Job erledigen wollen,
und zwar mit Werkzeugen die sich ihrem Willen anpassen. Bei Tcl ist jegliche
Funktionalität in Befehlen ausgeführt, selbst Dinge wie Schleifen und
Mathematische-Funktionen die bei anderen Sprachen normalerweise Teil der Syntax
sind. Das erlaubt Tcl in den Hintergrund von Domänen spezifischen Sprachen zu
treten die das jeweilige Projekt gerade benötigt. Die Tcl-Syntax ist sehr
leichtgewichtig. Sie ist selbst leichtgewichtiger als die Syntax von Lisp.
Tcl steht dir einfach nicht im Weg.
```tcl
#! /bin/env tclsh
################################################################################
## 1. Richtlinien
################################################################################
# Tcl ist nicht Bash oder C! Das muss gesagt werden, denn standard Shell-Quoting
# funktioniert fast mit Tcl. Daher glauben viele sie können diese Syntax für
# Tcl übernehmen. Am Beginn funktioniert das meist, führt aber schnell zu
# Frustrationen wenn die Skripte komplexer werden.
# Eckige-Klammern sind nur Quoting-Mechanismen, keine Code-Block-Konstruktoren
# und auch keine Listen-Konstruktoren. In Tcl gibt es diese beiden Dinge nicht.
# Eckige-Klammern werden verwendet um Spezial-Zeichen in Prozeduren zu escapen
# und in Zeichenketten die als Listen formatiert sind.
################################################################################
## 2. Syntax
################################################################################
# Jede Zeile ist ein Befehl. Das erste Wort ist der Name des Befehls, jedes
# weitere Wort ist ein Argument des Befehls. Wörter sind begrenzt durch
# Leerzeichen. Da jedes Wort auch ein String ist, sind keine speziellen
# Auszeichnungen wie Anführungs-Zeichen, Klammern oder Backslashes nötig.
# Selbst wenn Anführungs-Zeichen verwendet werden, denn sie sind ja keine
# String-Konstruktoren, sondern nur Escape-Zeichen.
set greeting1 Sal
set greeting2 ut
set greeting3 ations
# Strichpunkte begrenzen auch Befehle
set greeting1 Sal; set greeting2 ut; set greeting3 ations
# Das Dollar-Zeichen zeigt eine Variablen-Substitution an.
set greeting $greeting1$greeting2$greeting3
# Eckige-Klammern zeigen Befehls-Substitionen an. Das Ergebnis des Befehls wird an
# Stelle des Klammern-Ausdrucks eingefügt. Wenn man dem "set" Befehl nur den
# Namen einer Variablen übergibt, gibt er den Wert der Variablen zurück.
set greeting $greeting1$greeting2[set greeting3]
# Befehls-Substitution sollte eigentlich Script-Substitution heißen, denn ein
# komplettes Script, und nicht nur ein Befehl, kann zwischen die Eckigen-Klammern
# geschrieben werden. Der "incr" Befehl erhöht den Wert einer Variable um 1
# und gibt den neuen Wert der Variable zurück.
set greeting $greeting[
incr i
incr i
incr i
]
# Der Backslash unterdrück die Bedeutung von Sonderzeichen
set amount \$16.42
# Der Backslash macht bestimmte Zeichen zu Sonderzeichen
puts lots\nof\n\n\n\n\n\nnewlines
# Ein Wort das in geschweiften Klammern eingeschlossen wurde ist von jeglichen
# speziellen Interpretationen ausgeschlossen. Eine Ausnahme bilden Backslashes
# vor geschweiften Klammern, hiermit wird die geschweifte Klammer von der Suche
# nach der schließenden geschweiften Klammer ausgeschlossen.
set somevar {
Das ist ein literales $ Zeichen, diese geschweifte Klammer \} wird nicht
als Ende interpretiert.
}
# Bei einem Wort das in doppelten Anführungszeichen steht verlieren Leerzeichen
# ihre spezielle Bedeutung.
set name Neo
set greeting "Hallo, $name"
#Variablen-Namen können irgend eine Zeichenkette sein.
set {first name} New
# Die Geschweifte-Klammern-Form der Variablen-Substitution kann sehr komplexe
# Variblen-Namen handhaben.
set greeting "Hello, ${first name}"
# Der "set" Befehl kann immer anstatt einer Variablen-Substition verwendet
# werden.
set greeting "Hello, [set {first name}]"
# Mit dem Expansions-Operator "{*}" werden Wörter innerhalb eines Wortes wieder
# individuell als Teile des aktuellen Befehls behandelt.
set {*}{name Neo}
# Ist Äquivalent zu
set name Neo
# Ein Array ist eine spezielle Varible die also Kontainer für andere Variablen
# dient.
set person(name) Neo
set person(gender) male
set greeting "Hello, $person(name)"
# Ein Namensraum enthält Befehle und Variablen
namespace eval people {
namespace eval person1 {
variable name Neo
}
}
#Der volle Name einer Variablen beihaltet den/die umschließenden
# Namensraum/Namensräume begrenzt durch zwei Doppelpunkte.
set greeting "Hello $people::person1::name"
```
```tcl
################################################################################
## 3. Einige Notizen
################################################################################
# Jede weitere Funktion ist über Befehle implementiert. Von nun an kommt keine
# neue Syntax hinzu. Alles weitere das es über Tcl zu lernen gibt ist das
# Verhalten individueller Befehle und die bedeutung ihrer Argumente.
# Um einen Interpreter zu bekommen mit dem man nichts mehr machen kann, lösche
# einfach den globalen Namensraum. Das ist nicht sehr sinnvoll, zeigt aber die
# Natur von Tcl.
namespace delete ::
# Wegen des Verhaltens der Namens-Auflösung ist es sicherer den "variable"
# Befehl zu verwenden um in einem Namensraum einen Wert zu deklarieren oder
# zuzuweisen. Wenn eine Variable mit dem namen "name" bereits im globalen
# Namensraum existiert, bewirkt der "set" Befehl das der globalen Variable ein
# Wert zugewiesen wird, anstatt eine Variable im lokalen Namensraum zu erzeugen
namespace eval people {
namespace eval person1 {
variable name Neo
}
}
# Es kann immer der vollständige Name einer Variable verwendet werden, falls
# gewünscht.
set people::person1::name Neo
################################################################################
## 4. Befehle
################################################################################
# Berechnungen werde mit dem "expr" Befehl durchgeführt.
set a 3
set b 4
set c [expr {$a + $b}]
# Since "expr" performs variable substitution on its own, brace the expression
# to prevent Tcl from performing variable substitution first. See
# Da der "expr" Befehl eigene Variablen-Substitutionen durchführt, setze den
# zu berechnenden Ausdruck in Eckige-Klammern. Das hindert Tcl daran Variablen-
# Substitutionen durchzuführen. Für Details siehe:
# "http://wiki.tcl.tk/Brace%20your%20#%20expr-essions"
# Der "expr" Befehl versteht Variablen- und Befehls-Substitutionen
set c [expr {$a + [set b]}]
# Der "expr" Befehl stellt Mathematische-Funktionen zur Verfügung.
set c [expr {pow($a,$b)}]
# Mathematische Operatoren sind als Befehle auch im Namensraum
# ::tcl::mathop verfügbar.
::tcl::mathop::+ 5 3
# Befehle können aus anderen Namensräumen importiert werden.
namespace import ::tcl::mathop::+
set result [+ 5 3]
# Neu Befehle werden mit dem "proc" Befehl gebildet.
proc greet name {
return "Hello, $name!"
}
#Es können mehrere Parameter spezifiziert werden.
proc greet {greeting name} {
return "$greeting, $name!"
}
# Wie bereits erwähnt, geschwungene Klammern erzeugen keinen Code-Block.
# Jeder Wert, sogar das dritte Argument für den "proc" Befehl ist eine
# Zeichenkette. Der vorherige Befehl kann daher auch ohne
# geschwungene Klammern geschrieben werden:
proc greet greeting\ name return\ \"Hello,\ \$name!
# Wenn der letzte Parameter der literale Wert "args" ist, sammelt dieser Wert
# alle übrigen Argumente des Befehls ein wenn dieser aufgerufen wird.
proc fold {cmd args} {
set res 0
foreach arg $args {
set res [$cmd $res $arg]
}
}
fold ::tcl::mathop::* 5 3 3 ;# -> 45
# Bedingte Ausführung ist auch als Befehl implementiert
if {3 > 4} {
puts {This will never happen}
} elseif {4 > 4} {
puts {This will also never happen}
} else {
puts {This will always happen}
}
# Auch Schleifen sind Befehle. Das erste, zweite und dritte Argument des "for"
# Befehls wird als mathematischer Ausdruck behandelt.
for {set i 0} {$i < 10} {incr i} {
set res [expr {$res + $i}]
}
# Das erste Argument des "while" Befehls wird auch als mathematischer Ausdruck
# behandelt.
set i 0
while {$i < 10} {
incr i 2
}
# Eine Liste ist eine speziell formatierte Zeichenkette. Im einfachsten Fall
# genügen Leerzeichen als Trennzeichen zwischen den einzelnen Werten.
set amounts 10\ 33\ 18
set amount [lindex $amounts 1]
# Geschwungene Klammern und Backslashes können verwendet werden um komplexe
# Werte in einer Liste zu formatieren. Eine Liste sieht aus wie ein Skript,
# allerdings verlieren verlieren Zeilenumbrüche und Doppelüunkte ihre
# besondere Bedeutung. Diese Funktionalität macht Tcl homoikonisch. Die
# folgende Liste enhtält drei Elemente.
set values {
one\ two
{three four}
five\{six
}
# Da Listen auch Zeichenketten sind, kann man Zeichenketten-Operationen auf
# ihnen anwenden. Allerdings mit dem Risiko die Formatierung der Liste zu
# beschädigen.
set values {one two three four}
set values [string map {two \{} $values] ;# $values is no-longer a \
properly-formatted listwell-formed list
# Der sicherste Weg korrekt formatierte Liste zu erzeugen, ist den "list"
# Befehl zu verwenden.
set values [list one \{ three four]
lappend values { } ;# Ein Leerzeichen als Element der Liste hinzufügen
# Mit "eval" können Werte als Skripts evaluiert weden.
eval {
set name Neo
set greeting "Hello, $name"
}
# Eine Liste kann immer an "eval" übergeben werden, solange die Liste einen
# einzigen Befehl entält.
eval {set name Neo}
eval [list set greeting "Hello, $name"]
# Daher: Wenn "eval" verwendet wird, verwende [list] um den gewünschten Befehl
# aufzubauen.
set command {set name}
lappend command {Archibald Sorbisol}
eval $command
# Es ist ein häufiger Fehler die Listen funktionen beim Aufbauen von Listen
# nicht zu verwenden.
set command {set name}
append command { Archibald Sorbisol}
eval $command ;# Hier passiert eine Fehler, denn der "set" Befehl hat nun zu \
viele Argumente {set name Archibald Sorbisol}
# Dieser Fehler kann auch leicht beim "subst" Befehl passieren.
set replacement {Archibald Sorbisol}
set command {set name $replacement}
set command [subst $command]
eval $command ;# The same error as before: too many arguments to "set" in \
{set name Archibald Sorbisol}
# Die korrekte Vorgangsweise ist es den substituierten Wert mit dem "list"
# Befehl zu formatieren.
set replacement [list {Archibald Sorbisol}]
set command {set name $replacement}
set command [subst $command]
eval $command
# Der "list" Befehl wird sehr häufig verwendet um Werte zu formatieren die
# in Tcl Skript Vorlagen substituiert werden. Es gibt dazu viele Beispiele,
# siehe unterhalb.
# Der "apply" Befehl evaluiert eine Zeichenkette als Befehl.
set cmd {{greeting name} {
return "$greeting, $name!"
}}
apply $cmd Whaddup Neo
# Der "uplevel" Befehl evaluiert ein Skript in einem höher liegenden
Gültigkeitsbereich.
proc greet {} {
uplevel {puts "$greeting, $name"}
}
proc set_double {varname value} {
if {[string is double $value]} {
uplevel [list variable $varname $value]
} else {
error [list {not a double} $value]
}
}
# Der "upvar" Befehl verknüpft eine Variable im aktuellen Gültigkeitsbereich
# mit einer Variable in einem höher liegenden Gültigkeitsbereich.
proc set_double {varname value} {
if {[string is double $value]} {
upvar 1 $varname var
set var $value
} else {
error [list {not a double} $value]
}
}
# Werde den eingebauten "while" Befehl los.
rename ::while {}
# Definieren einen neuen "while" Befehl mit hilfe des "proc" Befehls.
# Ausführlichere Fehler-Behandlung wird dem Leser als Übung überlassen.
proc while {condition script} {
if {[uplevel 1 [list expr $condition]]} {
uplevel 1 $script
tailcall [namespace which while] $condition $script
}
}
# Der "coroutine" Befehl erzeugt einen separaten Call-Stack, zusammen mit einem
# Befehl um diesem Call-Stack zu verwenden. Der "yield" Befehl unterbricht
# die Ausführung des aktuellen Call-Stacks.
proc countdown {} {
#send something back to the initial "coroutine" command
yield
set count 3
while {$count > 1} {
yield [incr count -1]
}
return 0
}
coroutine countdown1 countdown
coroutine countdown2 countdown
puts [countdown 1] ;# -> 2
puts [countdown 2] ;# -> 2
puts [countdown 1] ;# -> 1
puts [countdown 1] ;# -> 0
puts [coundown 1] ;# -> invalid command name "countdown1"
puts [countdown 2] ;# -> 1
```
## Referenzen
[Official Tcl Documentation](http://www.tcl.tk/man/tcl/)
[Tcl Wiki](http://wiki.tcl.tk)
[Tcl Subreddit](http://www.reddit.com/r/Tcl)
|