diff options
Diffstat (limited to 'de-de')
-rw-r--r-- | de-de/haml-de.html.markdown | 156 | ||||
-rw-r--r-- | de-de/lua-de.html.markdown | 426 | ||||
-rw-r--r-- | de-de/tcl-de.html.markdown | 475 |
3 files changed, 1057 insertions, 0 deletions
diff --git a/de-de/haml-de.html.markdown b/de-de/haml-de.html.markdown new file mode 100644 index 00000000..7272b365 --- /dev/null +++ b/de-de/haml-de.html.markdown @@ -0,0 +1,156 @@ +--- +language: haml +filename: learnhaml-de.haml +contributors: + - ["Simon Neveu", "https://github.com/sneveu"] + - ["Sol Bekic", "https://github.com/S0lll0s"] +lang: de-de +--- + +Haml ist eine Markup- und Templatingsprache, aufgesetzt auf Ruby, mit der HTML Dokumente einfach beschrieben werden können. + +Haml vermindert Wiederholung und Fehleranfälligkeit, indem es Tags basierend auf der Markup-Struktur schließt und schachtelt. +Dadurch ergibt sich kurzes, präzises und logisches Markup. + +Haml kann außerhalb eines Ruby-projekts verwendet werden. Mit dem installierten Haml gem kann man das Terminal benutzen um Haml zu HTML umzuwandeln: + +$ haml input_file.haml output_file.html + + +```haml +/ ------------------------------------------- +/ Einrückung +/ ------------------------------------------- + +/ + Einrückung ist ein wichtiges Element des Haml Syntax, deswegen ist es + wichtig ein konsequentes Schema zu verwenden. Meistens werden zwei spaces + verwendet, solange die Einrückungen das gleiche Schema verfolgen können + aber auch andere Breiten und Tabs verwendet werden + + +/ ------------------------------------------- +/ Kommentare +/ ------------------------------------------- + +/ Kommentare beginnen mit einem Slash + +/ + Mehrzeilige Kommentare werden eingerückt und mit einem Slash + eingeführt + +-# Diese Zeile ist ein "stummes" Kommentar, es wird nicht mitgerendert + + +/ ------------------------------------------- +/ HTML Elemente +/ ------------------------------------------- + +/ Tags werden durch ein Prozentzeichen und den Tagnamen erzeugt +%body + %header + %nav + +/ Die Zeilen oben würden folgendes ergeben: + <body> + <header> + <nav></nav> + </header> + </body> + +/ Text kann direkt nach dem Tagnamen eingefügt werden: +%h1 Headline copy + +/ Mehrzeilige Inhalte müssen stattdessen eingerückt werden: +%p + This is a lot of content that we could probably split onto two + separate lines. + +/ + HTML kann mit &= escaped werden. So werden HTML-sensitive Zeichen + enkodiert. Zum Beispiel: + +%p + &= "Ja & Nein" + +/ würde 'Ja & Nein' ergeben + +/ HTML kann mit != dekodiert werden: +%p + != "so schreibt man ein Paragraph-Tag: <p></p>" + +/ ...was 'This is how you write a paragraph tag <p></p>' ergeben würde + +/ CSS Klassen können mit '.classname' an Tags angehängt werden: +%div.foo.bar + +/ oder über einen Ruby Hash: +%div{:class => 'foo bar'} + +/ Das div Tag wird standardmäßig verwendet, divs können also verkürzt werden: +.foo + +/ andere Attribute können über den Hash angegeben werden: +%a{:href => '#', :class => 'bar', :title => 'Bar'} + +/ Booleesche Attribute können mit 'true' gesetzt werden: +%input{:selected => true} + +/ data-Attribute können in einem eigenen Hash im :data key angegeben werden: +%div{:data => {:attribute => 'foo'}} + + +/ ------------------------------------------- +/ Verwendung von Ruby +/ ------------------------------------------- + +/ Mit dem = Zeichen können Ruby-werte evaluiert und als Tag-text verwendet werden: + +%h1= book.name + +%p + = book.author + = book.publisher + + +/ Code nach einem Bindestrich wird ausgeführt aber nicht gerendert: +- books = ['book 1', 'book 2', 'book 3'] + +/ So können zum Beispiel auch Blöcke verwendet werden: +- books.shuffle.each_with_index do |book, index| + %h1= book + + if book do + %p This is a book + +/ + Auch hier werden wieder keine End-Tags benötigt! + Diese ergeben sich aus der Einrückung. + + +/ ------------------------------------------- +/ Inline Ruby / Ruby Interpolation +/ ------------------------------------------- + +/ Ruby variablen können mit #{} in Text interpoliert werden: +%p dein bestes Spiel ist #{best_game} + + +/ ------------------------------------------- +/ Filter +/ ------------------------------------------- + +/ + Mit dem Doppelpinkt können Haml Filter benutzt werden. + Zum Beispiel gibt es den :javascript Filter, mit dem inline JS + geschrieben werden kann: + +:javascript + console.log('Dies ist ein <script>'); + +``` + +## Weitere Resourcen + +- [What is HAML?](http://haml.info/) - Eine gute Einleitung auf der Haml homepage (englisch) +- [Official Docs](http://haml.info/docs/yardoc/file.REFERENCE.html) - Die offizielle Haml Referenz (englisch) diff --git a/de-de/lua-de.html.markdown b/de-de/lua-de.html.markdown new file mode 100644 index 00000000..83f8506c --- /dev/null +++ b/de-de/lua-de.html.markdown @@ -0,0 +1,426 @@ +--- +language: Lua +contributors: + - ["Tyler Neylon", "http://tylerneylon.com/"] +translators: + - ["Martin Schimandl", "https://github.com/Git-Jiro"] +filename: learnlua-de.lua +lang: de-de +--- + +```lua +-- Zwei Gedankenstriche starten ein einzeiliges Kommentar. + +--[[ + Fügt man zwei '[' und ']' hinzu, + erzeugt man einen mehrzeiligen Kommentar. +--]] +-------------------------------------------------------------------------------- +-- 1. Variablen und Fluß-Kontrolle. +-------------------------------------------------------------------------------- + +num = 42 -- Alle Nummern sind vom Typ: Double. +-- Werd nicht nervös, 64-Bit Double haben 52 Bits zum Speichern von exakten +-- Ganzzahlen; Maschinen-Genauigkeit ist kein Problem für Ganzzahlen kleiner als +-- 52 Bit. + +s = 'walternate' -- Zeichenketten sind unveränderlich, wie bei Python. +t = "Doppelte Anführungszeichen sind auch OK" +u = [[ Doppelte eckige Klammern + beginnen und beenden + mehrzeilige Zeichenketten.]] +t = nil -- Undefineren von t; Lua hat einen Garbage Collection. + +-- Blöcke werden durch Schlüsselwörter wie do/end markiert: +while num < 50 do + num = num + 1 -- Es gibt Keine Operatoren wie ++ oder += +end + +-- If Bedingungen: +if num > 40 then + print('over 40') +elseif s ~= 'walternate' then -- ~= bedeutet ungleich + -- Gleichheits-Check == wie bei Python; OK für Zeichenketten. + io.write('not over 40\n') -- Standard ist stdout. +else + -- Variablen sind standardmäßig global. + thisIsGlobal = 5 -- Camel case ist üblich. + + -- So macht man eine Variable lokal: + local line = io.read() -- Lies die nächste Zeile von stdin. + + -- Zeichenketten zusammenführen mit dem .. Operator: + print('Winter is coming, ' .. line) +end + +-- Undefinierte Variablen geben nil zurück. +-- Das ist kein Fehler: +foo = anUnknownVariable -- Nun ist foo = nil. + +aBoolValue = false + +-- Nur nil und false sind unwahr; 0 and '' sind wahr! +if not aBoolValue then print('was false') end + +-- 'or' und 'and' sind "kurz-geschlossen". Das ist so ähnlich wie der a?b:c +-- operator in C/js: +-- in C/js: +ans = aBoolValue and 'yes' or 'no' --> 'no' + +karlSum = 0 +for i = 1, 100 do -- Ein Bereich inkludiert beide Enden. + karlSum = karlSum + i +end + +-- Verwende "100, 1, -1" als Breich für Countdowns: +fredSum = 0 +for j = 100, 1, -1 do fredSum = fredSum + j end + +-- Im Allgemeinen besteht ein Bereich aus: Anfang, Ende, [, Schrittweite]. + +-- Ein anderes Schleifen-Konstrukt: +repeat + print('Der Weg der Zukunft') + num = num - 1 +until num == 0 + +-------------------------------------------------------------------------------- +-- 2. Funktionen. +-------------------------------------------------------------------------------- + +function fib(n) + if n < 2 then return n end + return fib(n - 2) + fib(n - 1) +end + +-- Closures und anonyme Funktionen sind ok: +function adder(x) + -- Die zurückgegebene Funktion wird erzeugt wenn addr aufgerufen wird und merkt + -- sich den Wert von x: + return function (y) return x + y end +end +a1 = adder(9) +a2 = adder(36) +print(a1(16)) --> 25 +print(a2(64)) --> 100 + +-- Rückgabewerte, Funktions-Aufrufe und Zuweisungen funktionieren alle mit +-- Listen die nicht immer gleich lang sein müssen. Überzählige Empfänger +-- bekommen nil; überzählige Sender werden ignoriert. + +x, y, z = 1, 2, 3, 4 +-- Nun ist x = 1, y = 2, z = 3, und 4 wird ignoriert. + +function bar(a, b, c) + print(a, b, c) + return 4, 8, 15, 16, 23, 42 +end + +x, y = bar('zaphod') --> prints "zaphod nil nil" +-- Nun ist x = 4, y = 8, die Werte 15..42 werden ignoriert. + +-- Funktionen sind erste Klasse, und können lokal oder global sein. +-- Das ist alles das Gleiche: +function f(x) return x * x end +f = function (x) return x * x end + +-- Das auch: +local function g(x) return math.sin(x) end +local g = function(x) return math.sin(x) end +-- Äquivalent zu local function g(x)..., außer das Referenzen auf g im +-- Funktions-Körper nicht wie erwartet funktionieren. +local g; g = function (x) return math.sin(x) end +-- Die Deklaration 'local g' macht Selbst-Referenzen auf g OK. + +-- Nebenbei gesagt, Trigonometrie-Funktionen verwenden Radianten. + +-- Funktionsaufrufe mit nur einem Zeichenketten-Parameter brauch keine runden +-- Klammern. +print 'hello' -- Funktioniert wunderbar. + +-- Funktionsaufrufe mit einem Tabellen-Parameter brauchen auch keine runden +-- Klammern. Mehr zu Tabellen kommt später. +print {} -- Funktioniert auch wunderbar. + +-------------------------------------------------------------------------------- +-- 3. Tabellen. +-------------------------------------------------------------------------------- + +-- Tabellen sind die einzige zusammengesetzte Struktur in Lua. Sie sind +-- assoziative Arrays. Sie sind so ähnlich wie PHP arrays oder JavaScript +-- Objekte. Sie sind Hash-Lookup-Dictionaries die auch als Listen verwendet +-- werden können. + +-- Verwenden von Tabellen als Dictionaries oder Maps: + +-- Dict-Literale haben standardmäßig Zeichenketten als Schlüssel: +t = {key1 = 'value1', key2 = false} + +-- Zeichenketten-Schlüssel verwenden eine JavaScript ähnliche Punkt-Notation. +print(t.key1) -- Ausgabe 'value1'. +t.newKey = {} -- Neues Schlüssel/Wert-Paar hinzufügen. +t.key2 = nil -- key2 aus der Tabelle entfernen. + +-- Literale notation für jeden (nicht-nil) Wert als Schlüssel: +u = {['@!#'] = 'qbert', [{}] = 1729, [6.28] = 'tau'} +print(u[6.28]) -- Ausgabe "tau" + +-- Schlüssel-Vergleiche funktionieren per Wert für Nummern und Zeichenketten, +-- aber über die Identität bei Tabellen. +a = u['@!#'] -- Nun ist a = 'qbert'. +b = u[{}] -- Wir würden 1729 erwarten, aber es ist nil: +-- b = nil weil der Lookup fehlschlägt. Er schlägt Fehl, weil der Schlüssel +-- den wir verwendet haben nicht das gleiche Objekt ist das wir verwendet +-- haben um den original Wert zu speichern. Zahlen und Zeichnkette sind daher +-- die praktischeren Schlüssel. + +-- Eine Funktion mit nur einem Tabellen-Parameter benötigt keine Klammern. +function h(x) print(x.key1) end +h{key1 = 'Sonmi~451'} -- Ausgabe 'Sonmi~451'. + +for key, val in pairs(u) do -- Tabellen-Iteration. + print(key, val) +end + +-- _G ist eine spezielle Tabelle die alles Globale enthält. +print(_G['_G'] == _G) -- Ausgabe 'true'. + +-- Verwenden von Tabellen als Listen/Arrays: + +-- Listen-Literale verwenden implizit Ganzzahlen als Schlüssel: +v = {'value1', 'value2', 1.21, 'gigawatts'} +for i = 1, #v do -- #v ist die Größe von v für Listen. + print(v[i]) -- Indices beginnen mit 1 !! SO VERRÜCKT! +end +-- Eine 'Liste' ist kein echter Typ. v ist nur eine Tabelle mit fortlaufenden +-- Ganzzahlen als Schlüssel, die behandelt wird wie eine Liste. + +-------------------------------------------------------------------------------- +-- 3.1 Metatabellen und Metamethoden +-------------------------------------------------------------------------------- + +-- Eine Tabelle kann eine Metatabelle haben. Diese verleiht ihr so etwas wie +-- Tabellen-Operator-Überladungs-Verhalten. Später sehen wir wie +-- Metatabellen js-prototypen artiges Verhalten unterstützen. + +f1 = {a = 1, b = 2} -- Repräsentiert den Bruch a/b. +f2 = {a = 2, b = 3} + +-- Dies würde Fehlschlagen: +-- s = f1 + f2 + +metafraction = {} +function metafraction.__add(f1, f2) + local sum = {} + sum.b = f1.b * f2.b + sum.a = f1.a * f2.b + f2.a * f1.b + return sum +end + +setmetatable(f1, metafraction) +setmetatable(f2, metafraction) + +s = f1 + f2 -- Rufe __add(f1, f2) vom der Metatabelle von f1 auf. + +-- f1 und f2 haben keine Schlüssel für ihre Metatabellen, anders als bei js +-- Prototypen. Daher muss mithilfe von getmetatable(f1) darauf zugegriffen +-- werden. Eine Metatabelle ist wie eine normale Tabelle mit Schlüsseln die +-- Lua bekannt sind, so wie __add. + + +-- Die nächste Zeile schlägt fehl weil s keine Metatabelle hat: +-- t = s + s +-- Mihilfe von Klassen ähnlichen Mustern kann das gelöst werden. +-- Siehe weiter unten. + +-- Ein __index einer Metatabelle überlädt Punkt-Lookups: +defaultFavs = {animal = 'gru', food = 'donuts'} +myFavs = {food = 'pizza'} +setmetatable(myFavs, {__index = defaultFavs}) +eatenBy = myFavs.animal -- Funktioniert dank Metatabelle! + +-------------------------------------------------------------------------------- +-- Direkte Tabellen-Lookups die fehlschlagen werden mithilfe von __index der +-- Metatabelle wiederholt. Das geschieht rekursiv. + +-- __index kann auch eine Funktion mit der Form function(tbl, key) sein. +-- Damit kann man Lookups weiter anpassen. + +-- Werte wie __index,add, .. werden Metamethoden genannt. +-- HIer eine vollständige Liste aller Metamethoden. + +-- __add(a, b) für a + b +-- __sub(a, b) für a - b +-- __mul(a, b) für a * b +-- __div(a, b) für a / b +-- __mod(a, b) für a % b +-- __pow(a, b) für a ^ b +-- __unm(a) für -a +-- __concat(a, b) für a .. b +-- __len(a) für #a +-- __eq(a, b) für a == b +-- __lt(a, b) für a < b +-- __le(a, b) für a <= b +-- __index(a, b) <fn or a table> für a.b +-- __newindex(a, b, c) für a.b = c +-- __call(a, ...) für a(...) + +-------------------------------------------------------------------------------- +-- 3.2 Klassen-Artige Tabellen und Vererbung. +-------------------------------------------------------------------------------- + +-- Klassen sind in Lua nicht eingebaut. Es gibt verschieden Wege sie mithilfe +-- von Tabellen und Metatabellen zu erzeugen. + +-- Die Erklärund des Beispiels erfolgt unterhalb. + +Dog = {} -- 1. + +function Dog:new() -- 2. + local newObj = {sound = 'woof'} -- 3. + self.__index = self -- 4. + return setmetatable(newObj, self) -- 5. +end + +function Dog:makeSound() -- 6. + print('I say ' .. self.sound) +end + +mrDog = Dog:new() -- 7. +mrDog:makeSound() -- 'I say woof' -- 8. + +-- 1. Dog verhält sich wie eine Klasse; Ist aber eine Tabelle. +-- 2. "function tablename:fn(...)" ist das gleiche wie +-- "function tablename.fn(self, ...)", Der : fügt nur ein Argument namens +-- self hinzu. Siehe 7 & 8 um zu sehen wie self seinen Wert bekommt. +-- 3. newObj wird eine Instanz von Dog. +-- 4. "self" ist die zu Instanzierende Klasse. Meistern ist self = Dog, aber +-- dies kann durch Vererbung geändert werden. newObj bekommt die Funktionen +-- von self wenn wir die Metatabelle von newObj und __index von self auf +-- self setzen. +-- 5. Zur Erinnerung: setmetatable gibt sein erstes Argument zurück. +-- 6. Der Doppelpunkt funktioniert wie bei 2, aber dieses Mal erwarten wir das +-- self eine Instanz ist und keine Klasse. +-- 7. Das Selbe wie Dog.new(Dog), also self = Dog in new(). +-- 8. Das Selbe wie mrDog.makeSound(mrDog); self = mrDog. + +-------------------------------------------------------------------------------- + +-- Vererbungs-Beispiel: + +LoudDog = Dog:new() -- 1. + +function LoudDog:makeSound() + local s = self.sound .. ' ' -- 2. + print(s .. s .. s) +end + +seymour = LoudDog:new() -- 3. +seymour:makeSound() -- 'woof woof woof' -- 4. + +-------------------------------------------------------------------------------- +-- 1. LoudDog bekommt die Methoden und Variablen von Dog. +-- 2. self hat einen 'sound' Schlüssel von new(), siehe 3. +-- 3. Das Gleiche wie "LoudDog.new(LoudDog)", und umgewandelt zu "Dog.new(LoudDog)" +-- denn LoudDog hat keinen 'new' Schlüssel, aber "__index = Dog" steht in der +-- Metatabelle. +-- Ergebnis: Die Metatabelle von seymour ist LoudDog und "LoudDog.__index = Dog". +-- Daher ist seymour.key gleich seymour.key, LoudDog.key, Dog.key, je nachdem +-- welche Tabelle als erstes einen passenden Schlüssel hat. +-- 4. Der 'makeSound' Schlüssel wird in LoudDog gefunden: Das ist das Gleiche +-- wie "LoudDog.makeSound(seymour)". + +-- Wenn nötig, sieht new() einer Sub-Klasse genau so aus wie new() der +-- Basis-Klasse: +function LoudDog:new() + local newObj = {} + -- set up newObj + self.__index = self + return setmetatable(newObj, self) +end + +-------------------------------------------------------------------------------- +-- 4. Module. +-------------------------------------------------------------------------------- + + +--[[ Dieser Abschnitt ist auskommentiert damit der Rest des Skripts lauffähig +-- bleibt. +``` + +```lua +-- Angenommen mod.lua sieht so aus: +local M = {} + +local function sayMyName() + print('Hrunkner') +end + +function M.sayHello() + print('Why hello there') + sayMyName() +end + +return M + +-- Eine andere Datei könnte die Funktionen in mod.lua so verwenden: +local mod = require('mod') -- Führe mod.lua aus. + +-- require ist der Standard-Weg um Module zu inkludieren. +-- require verhält sich wie: (Wenn nicht gecached wird; siehe später) +local mod = (function () + <Inhalt von mod.lua> +end)() +-- Es ist als ob mod.lua eine Funktion wäre, sodass lokale Variablen in +-- mod.lua ausserhalb unsichtbar sind. + +-- Das funktioniert weil mod hier das Gleiche wie M in mod.lua ist: +mod.sayHello() -- Says hello to Hrunkner. + +-- Das ist Falsch: sayMyName existiert nur in mod.lua: +mod.sayMyName() -- Fehler + +-- Der Rückgabe-Wert von require wird zwischengespeichert. Sodass Module nur +-- einmal abgearbeitet werden, auch wenn sie mit require öfters eingebunden +-- werden. + +-- Nehmen wir an mod2.lua enthält "print('Hi!')". +local a = require('mod2') -- Ausgabe Hi! +local b = require('mod2') -- Keine Ausgabe; a=b. + +-- dofile ist wie require aber ohne Zwischenspeichern. +dofile('mod2') --> Hi! +dofile('mod2') --> Hi! (läuft nochmal, nicht wie require) + +-- loadfile ladet eine lua Datei aber die Datei wird noch nicht abgearbeitet. +f = loadfile('mod2') -- Sobald f() aufgerufen wird läuft mod2.lua. + +-- loadstring ist loadfile für Zeichenketten +g = loadstring('print(343)') -- Gibt eine Funktion zurück.. +g() -- Ausgabe 343; Vorher kam keine Ausgabe. + +--]] + +``` +## Referenzen + +Ich war so begeistert Lua zu lernen, damit ich Spiele mit <a href="http://love2d.org/">Love 2D game engine</a> programmieren konnte. + +Ich habe angefangen mit <a href="http://nova-fusion.com/2012/08/27/lua-for-programmers-part-1/">BlackBulletIV's Lua for programmers</a>. +Danach habe ich das offizielle Lua Buch gelesen: <a href="http://www.lua.org/pil/contents.html">Programming in Lua</a> + +Es kann auch hilfreich sein hier vorbeizuschauen: <a href="http://lua-users.org/files/wiki_insecure/users/thomasl/luarefv51.pdf">Lua short +reference</a> + +Wichtige Themen die hier nicht angesprochen wurden; die Standard-Bibliotheken: + +* <a href="http://lua-users.org/wiki/StringLibraryTutorial">string library</a> +* <a href="http://lua-users.org/wiki/TableLibraryTutorial">table library</a> +* <a href="http://lua-users.org/wiki/MathLibraryTutorial">math library</a> +* <a href="http://lua-users.org/wiki/IoLibraryTutorial">io library</a> +* <a href="http://lua-users.org/wiki/OsLibraryTutorial">os library</a> + +Übrigends, die gesamte Datei ist gültiges Lua. Speichere sie als learn.lua und +starte sie als "lua learn.lua" ! + +Die Erstfassung ist von tylerneylon.com, und ist auch hier verfügbar: <a href="https://gist.github.com/tylerneylon/5853042">github gist</a>. Viel Spaß mit Lua! diff --git a/de-de/tcl-de.html.markdown b/de-de/tcl-de.html.markdown new file mode 100644 index 00000000..4f3b8820 --- /dev/null +++ b/de-de/tcl-de.html.markdown @@ -0,0 +1,475 @@ +--- +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 Script-Sprache 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 Scipt-Sprache 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-Bilbiothek 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 zuätzlichen Speicher-Overhead. Prozeduren werden +automatisch byte-kompiliert außer sie verwenden dynamsiche 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 Wissenshaftlern 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 spezischen 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 formattiert 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) |