summaryrefslogtreecommitdiffhomepage
path: root/de-de
diff options
context:
space:
mode:
Diffstat (limited to 'de-de')
-rw-r--r--de-de/bash-de.html.markdown223
-rw-r--r--de-de/git-de.html.markdown30
-rw-r--r--de-de/go-de.html.markdown71
-rw-r--r--de-de/hack-de.html.markdown322
-rw-r--r--de-de/haml-de.html.markdown156
-rw-r--r--de-de/haskell-de.html.markdown101
-rw-r--r--de-de/latex-de.html.markdown91
-rw-r--r--de-de/lua-de.html.markdown426
-rw-r--r--de-de/make-de.html.markdown260
-rw-r--r--de-de/markdown-de.html.markdown10
-rw-r--r--de-de/scala-de.html.markdown518
-rw-r--r--de-de/tcl-de.html.markdown475
-rw-r--r--de-de/yaml-de.html.markdown4
13 files changed, 2286 insertions, 401 deletions
diff --git a/de-de/bash-de.html.markdown b/de-de/bash-de.html.markdown
index fb9cd9d4..541d28bb 100644
--- a/de-de/bash-de.html.markdown
+++ b/de-de/bash-de.html.markdown
@@ -28,18 +28,50 @@ echo Hello, world!
echo 'Dies ist die erste Zeile'; echo 'Dies die zweite Zeile'
# Variablen deklariert man so:
-VARIABLE="irgendein String"
+Variable="irgendein String"
# Aber nicht so:
-VARIABLE = "irgendein String"
-# Bash wird VARIABLE für einen Befehl halten, den es ausführen soll. Es wird einen Fehler ausgeben,
+Variable = "irgendein String"
+# Bash wird 'Variable' für einen Befehl halten, den es ausführen soll. Es wird einen Fehler ausgeben,
# weil es den Befehl nicht findet.
+# Und so auch nicht:
+Variable= 'Some string'
+# Bash wird 'Variable' wieder für einen Befehl halten, den es ausführen soll. Es wird einen Fehler ausgeben,
+# Hier wird der Teil 'Variable=' als nur für diesen einen Befehl gültige Zuweisung an die Variable gesehen.
+
# Eine Variable wird so benutzt:
-echo $VARIABLE
-echo "$VARIABLE"
-# Wenn du eine Variable selbst benutzt – ihr Werte zuweist, sie exportierst oder irgendetwas anders –,
+echo $Variable
+echo "$Variable"
+echo ${Variable}
+# aber
+echo '$Variable'
+# Wenn du eine Variable selbst benutzt – ihr Werte zuweist, sie exportierst oder irgendetwas anderes –,
# dann über ihren Namen ohne $. Aber wenn du ihren zugewiesenen Wert willst, dann musst du $ voranstellen.
+# Beachte: ' (Hochkomma) verhindert das Interpretieren der Variablen
+
+# Ersetzen von Zeichenketten in Variablen
+echo ${Variable/irgendein/neuer}
+# Ersetzt das erste Vorkommen von "irgendein" durch "neuer"
+
+# Teil einer Zeichenkette
+Laenge=7
+echo ${Variable:0:Laenge}
+# Gibt nur die ersten 7 Zeichen zurück
+
+# Standardwert verwenden
+echo ${Foo:-"ErsatzWennLeerOderUngesetzt"}
+# Das funktioniert mit nicht gesetzten Variablen (Foo=) und leeren Zeichenketten (Foo="")
+# Die Zahl 0 (Foo=0) liefert 0.
+# Beachte: der wert der Variablen wird nicht geändert
+
+# Eingebaute Variable (BUILTINS):
+# Einige nützliche Beispiele
+echo "Rückgabewert des letzten Befehls: $?"
+echo "Die PID des skripts: $$"
+echo "Anzahl der Argumente beim Aufruf: $#"
+echo "Alle Argumente beim Aufruf: $@"
+echo "Die Argumente in einzelnen Variablen: $1 $2..."
# Einen Wert aus der Eingabe lesen:
echo "Wie heisst du?"
@@ -47,14 +79,30 @@ read NAME # Wir mussten nicht mal eine neue Variable deklarieren
echo Hello, $NAME!
# Wir haben die übliche if-Struktur:
-if true
+# 'man test' liefert weitere Informationen zu Bedingungen
+if [ "$NAME" -ne $USER ]
then
- echo "Wie erwartet"
+ echo "Dein Name ist nicht dein Login-Name"
else
- echo "Und dies nicht"
+ echo "Dein Name ist dein Login-Name"
+fi
+
+# Es gibt auch bedingte Ausführung
+echo "immer ausgeführt" || echo "Nur ausgeführt wenn der erste Befehl fehlschlägt"
+echo "immer ausgeführt" && echo "Nur ausgeführt wenn der erste Befehl Erfolg hat"
+
+# Um && und || mit if statements zu verwenden, braucht man mehrfache Paare eckiger Klammern:
+if [ $NAME == "Steve" ] && [ $Alter -eq 15 ]
+then
+ echo "Wird ausgeführt wenn $NAME gleich 'Steve' UND $Alter gleich 15."
+fi
+
+if [ $Name == "Daniya" ] || [ $Name == "Zach" ]
+then
+ echo "Wird ausgeführt wenn $NAME gleich 'Daniya' ODER $NAME gleich 'Zach'."
fi
-# Ausdrücke werden im folgenden Format festgehalten:
+# Ausdrücke haben folgendes Format:
echo $(( 10 + 5 ))
# Anders als andere Programmiersprachen ist Bash eine Shell – es arbeitet also im Kontext von Verzeichnissen.
@@ -69,13 +117,60 @@ ls -l # Liste alle Dateien und Unterverzeichnisse auf einer eigenen Zeile auf
# txt-Dateien im aktuellen Verzeichnis auflisten:
ls -l | grep "\.txt"
-# Befehle können innerhalb anderer Befehle mit $( ) erstetzt werden:
+# Ein- und Ausgabe können umgeleitet werden (stdin, stdout, and stderr).
+# Von stdin lesen bis "EOF" allein in einer Zeile auftaucht
+# und die Datei hello.py mit den Zeilen zwischen den beiden "EOF"
+# überschreiben:
+cat > hello.py << EOF
+#!/usr/bin/env python
+from __future__ import print_function
+import sys
+print("#stdout", file=sys.stdout)
+print("#stderr", file=sys.stderr)
+for line in sys.stdin:
+ print(line, file=sys.stdout)
+EOF
+
+# Führe hello.py mit verschiedenen Umleitungen von
+# stdin, stdout und stderr aus:
+python hello.py < "input.in"
+python hello.py > "output.out"
+python hello.py 2> "error.err"
+python hello.py > "output-and-error.log" 2>&1
+python hello.py > /dev/null 2>&1
+# Die Fehlerausgabe würde die Datei "error.err" überschreiben (falls sie existiert)
+# verwende ">>" um stattdessen anzuhängen:
+python hello.py >> "output.out" 2>> "error.err"
+
+# Überschreibe output.out, hänge an error.err an und zähle die Zeilen beider Dateien:
+info bash 'Basic Shell Features' 'Redirections' > output.out 2>> error.err
+wc -l output.out error.err
+
+# Führe einen Befehl aus und gib dessen "file descriptor" (zB /dev/fd/123) aus
+# siehe: man fd
+echo <(echo "#helloworld")
+
+# Mehrere Arten, um output.out mit "#helloworld" zu überschreiben:
+cat > output.out <(echo "#helloworld")
+echo "#helloworld" > output.out
+echo "#helloworld" | cat > output.out
+echo "#helloworld" | tee output.out >/dev/null
+
+# Löschen der Hilfsdateien von oberhalb, mit Anzeige der Dateinamen
+# (mit '-i' für "interactive" erfolgt für jede Date eine Rückfrage)
+rm -v output.out error.err output-and-error.log
+
+# Die Ausgabe von Befehlen kann mit Hilfe von $( ) in anderen Befehlen verwendet weden:
# Der folgende Befehl zeigt die Anzahl aller Dateien und Unterverzeichnisse
# im aktuellen Verzeichnis an.
echo "Dieser Ordner beinhaltet $(ls | wc -l) Dateien und Verzeichnisse."
+# Dasselbe kann man mit "backticks" `` erreichen, aber diese können
+# nicht verschachtelt werden. $() ist die empfohlene Methode.
+echo "Dieser Ordner beinhaltet `ls | wc -l` Dateien und Verzeichnisse."
+
# Bash nutzt einen case-Ausdruck, der sich ähnlich wie switch in Java oder C++ verhält.
-case "$VARIABLE"
+case "$Variable"
in
# Liste der Fälle, die unterschieden werden sollen
0) echo "Hier ist eine Null."
@@ -83,10 +178,106 @@ in
*) echo "Das ist nicht Null."
esac
-# loops iterieren über die angegebene Zahl von Argumenten:
-# Der Inhalt von $VARIABLE wird dreimal ausgedruckt.
-for $VARIABLE in x y z
+# 'for' Schleifen iterieren über die angegebene Zahl von Argumenten:
+# Der Inhalt von $Variable wird dreimal ausgedruckt.
+for $Variable in {1..3}
do
- echo "$VARIABLE"
+ echo "$Variable"
done
+
+# Oder verwende die "traditionelle 'for'-Schleife":
+for ((a=1; a <= 3; a++))
+do
+ echo $a
+done
+
+# Schleifen können auch mit Dateien arbeiten:
+# 'cat' zeigt zuerst file1 an und dann file2
+for Variable in file1 file2
+do
+ cat "$Variable"
+done
+
+# .. oder mit der Ausgabe eines Befehls:
+# Ausgabe des Inhalts jeder Datei, die von 'ls' aufgezählt wird
+for Output in $(ls)
+do
+ cat "$Output"
+done
+
+# while Schleife:
+while [ true ]
+do
+ echo "Schleifenkörper..."
+ break
+done
+
+# Funktionen definieren
+# Definition:
+function foo ()
+{
+ echo "Argumente funktionieren wie bei skripts: $@"
+ echo Und: $1 $2..."
+ echo "Dies ist eine Funktion"
+ return 0
+}
+
+# oder einfacher
+bar ()
+{
+ echo "Auch so kann man Funktionen deklarieren!"
+ return 0
+}
+
+# Aufruf der Funktion:
+foo "My name is" $Name
+
+# Was du noch lernen könntest:
+# Ausgabe der letzten 10 Zeilen von file.txt
+tail -n 10 file.txt
+# Ausgabe der ersten 10 Zeilen von file.txt
+head -n 10 file.txt
+# sortierte Ausgabe von file.txt
+sort file.txt
+# Mehrfachzeilen in sortierten Dateien unterdrücken
+# oder (mit -d) nur diese ausgeben
+uniq -d file.txt
+# Ausgabe nur der ersten Spalte (vor dem ersten ',')
+cut -d ',' -f 1 file.txt
+# ersetze in file.txt jedes vorkommende 'gut' durch 'super' (versteht regex)
+sed -i 's/gut/super/g' file.txt
+# Ausgabe nach stdout aller Zeilen von file.txt, die auf eine regex passen
+# Im Beispiel: Zeilen, die mit "foo" beginnen und mit "bar" enden
+grep "^foo.*bar$" file.txt
+# Mit der Option "-c" wird stattdessen die Anzahl der gefundenen Zeilen ausgegeben
+grep -c "^foo.*bar$" file.txt
+# verwende 'fgrep' oder 'grep -F' wenn du buchstäblich nach den Zeichen
+# suchen willst, ohne sie als regex zu interpretieren
+fgrep "^foo.*bar$" file.txt
+
+# Dokumentation über die in bash eingebauten Befehle
+# bekommst du mit dem eingebauten Befehl 'help'
+help
+help help
+help for
+help return
+help source
+help .
+
+# Das bash-Handbuch liest du mit 'man'
+apropos bash
+man 1 bash
+man bash
+
+# Dann gibt es noch das 'info' System (drücke ? um Hilfe angezeigt zu bekommen)
+apropos info | grep '^info.*('
+man info
+info info
+info 5 info
+
+# info Dokumentation über bash:
+info bash
+info bash 'Bash Features'
+info bash 6
+info --apropos bash
```
diff --git a/de-de/git-de.html.markdown b/de-de/git-de.html.markdown
index 43939129..dea329d5 100644
--- a/de-de/git-de.html.markdown
+++ b/de-de/git-de.html.markdown
@@ -18,12 +18,12 @@ Anmerkung des Übersetzers: Einige englische Begriffe wie *Repository*, *Commit*
### Was ist Versionsverwaltung?
-Eine Versionskontrolle erfasst die Änderungen einer Datei oder eines Verzeichnisses im Verlauf der Zeit.
+Eine Versionsverwaltung erfasst die Änderungen einer Datei oder eines Verzeichnisses im Verlauf der Zeit.
### Zentrale im Vergleich mit verteilter Versionverwaltung
-* Zentrale Versionskontrolle konzentriert sich auf das Synchronisieren, Verfolgen und Sichern von Dateien.
-* Verteilte Versionskontrolle konzentriert sich auf das Teilen der Änderungen. Jede Änderung hat eine eindeutige ID.
+* Zentrale Versionsverwaltung konzentriert sich auf das Synchronisieren, Verfolgen und Sichern von Dateien.
+* Verteilte Versionsverwaltung konzentriert sich auf das Teilen der Änderungen. Jede Änderung hat eine eindeutige ID.
* Verteilte Systeme haben keine vorbestimmte Struktur. Ein SVN-ähnliches, zentrales System wäre mit Git ebenso umsetzbar.
[Weiterführende Informationen](http://git-scm.com/book/en/Getting-Started-About-Version-Control)
@@ -61,7 +61,7 @@ Der Index ist die die Staging-Area von Git. Es ist im Grunde eine Ebene, die Arb
### Commit
-Ein Commit ist ein Schnappschuss von Uderungen in deinem Arbeitsverzeichnis. Wenn du zum Beispiel 5 Dateien hinzugefügt und 2 andere entfernt hast, werden diese Änderungen im Commit (Schnappschuss) enthalten sein. Dieser Commit kann dann in andere Repositorys gepusht werden. Oder nicht!
+Ein Commit ist ein Schnappschuss von Änderungen in deinem Arbeitsverzeichnis. Wenn du zum Beispiel 5 Dateien hinzugefügt und 2 andere entfernt hast, werden diese Änderungen im Commit (Schnappschuss) enthalten sein. Dieser Commit kann dann in andere Repositories gepusht werden. Oder nicht!
### Branch
@@ -69,7 +69,9 @@ Ein Branch, ein Ast oder Zweig, ist im Kern ein Pointer auf den letzten Commit,
### HEAD und head (Teil des .git-Verzeichnisses)
-HEAD ist ein Pointer auf den aktuellen Branch. Ein Repository hat nur einen *aktiven* HEAD. Ein head ist ein Pointer, der auf ein beliebige Zahl von heads zeigt.
+HEAD ist ein Pointer auf den aktuellen Branch. Ein Repository hat nur einen *aktiven* HEAD.
+
+Ein *head* ist ein Pointer, der auf einen beliebigen Commit zeigt. Ein Repository kann eine beliebige Zahl von *heads* enthalten.
### Konzeptionelle Hintergründe
@@ -127,7 +129,7 @@ Zeigt die Unterschiede zwischen Index (im Grunde dein Arbeitsverzeichnis/-reposi
```bash
-# Zeigt den Branch, nicht-verfolgte Dateien, Uderungen und andere Unterschiede an
+# Zeigt den Branch, nicht-verfolgte Dateien, Änderungen und andere Unterschiede an
$ git status
# Anderes Wissenswertes über git status anzeigen
@@ -151,7 +153,7 @@ $ git add ./*.java
### branch
-Verwalte alle Branches. Du kannst sie mit diesem Befehl ansehen, bearbeiten, neue erschaffen oder löschen.
+Verwalte alle Branches. Du kannst sie mit diesem Befehl ansehen, bearbeiten, neue erzeugen oder löschen.
```bash
# Liste alle bestehenden Branches und Remotes auf
@@ -186,7 +188,7 @@ $ git checkout -b newBranch
### clone
-Ein bestehendes Repository in ein neues Verzeichnis klonen oder kopieren. Es fügt außerdem für hedes geklonte Repo remote-tracking Branches hinzu. Du kannst auf diese Remote-Branches pushen.
+Ein bestehendes Repository in ein neues Verzeichnis klonen oder kopieren. Es fügt außerdem für jedes geklonte Repository remote-tracking Branches hinzu. Du kannst auf diese Remote-Branches pushen.
```bash
# Klone learnxinyminutes-docs
@@ -288,16 +290,16 @@ $ git mv -f myFile existingFile
### pull
-Führe einen Pull, zieht alle Daten, eines Repositorys und f?? einen Merge mit einem anderen Branch durch.
+Führe einen Pull (zieht alle Daten eines Repositories) aus und führt einen Merge mit einem anderen Branch durch.
```bash
-# Update deines lokalen Repos, indem ein Merge der neuen Uderungen
-# von den remote-liegenden "origin"- und "master"-Branches durchgef?? wird.
+# Update deines lokalen Repos, indem ein Merge der neuen Änderungen
+# von den remote-liegenden "origin"- und "master"-Branches durchgeführt wird.
# git pull <remote> <branch>
# git pull => impliziter Verweis auf origin und master
$ git pull origin master
-# F?? einen Merge von Uderungen eines remote-Branch und ein Rebase
+# Führt einen Merge von Änderungen eines remote-Branch und ein Rebase
# des Branch-Commits im lokalen Repo durch. Wie: pull <remote> <branch>, git rebase <branch>"
$ git pull origin master --rebase
```
@@ -337,8 +339,8 @@ $ git reset
# Setze die Staging-Area zurück, um dem letzten Commit zu entsprechen und überschreibe das Arbeitsverzeichnis
$ git reset --hard
-# Bewegt die Spitze des Branches zu dem angegebenen Commit (das Verzeichnis bleibt unber??)
-# Alle Uderungen bleiben im Verzeichnis erhalten
+# Bewegt die Spitze des Branches zu dem angegebenen Commit (das Verzeichnis bleibt unberührt)
+# Alle Änderungen bleiben im Verzeichnis erhalten
$ git reset 31f2bb1
# Bewegt die Spitze des Branches zurück zu dem angegebenen Commit
diff --git a/de-de/go-de.html.markdown b/de-de/go-de.html.markdown
index 7e61bf81..dca88f01 100644
--- a/de-de/go-de.html.markdown
+++ b/de-de/go-de.html.markdown
@@ -4,17 +4,17 @@ filename: learngo-de.go
contributors:
- ["Joseph Adams", "https://github.com/jcla1"]
- ["Dennis Keller", "https://github.com/denniskeller"]
+translators:
+ - ["Jerome Meinke", "https://github.com/jmeinke"]
lang: de-de
---
-Go wurde entwickelt, um Probleme zu lösen. Sie ist zwar nicht der neueste Trend in
-der Informatik, aber sie ist einer der neuesten und schnellsten Wege, um Aufgabe in
-der realen Welt zu lösen.
-
-Sie hat vertraute Elemente von imperativen Sprachen mit statischer Typisierung
-und kann schnell kompiliert und ausgeführt werden. Verbunden mit leicht zu
-verstehenden Parallelitäts-Konstrukten, um die heute üblichen mehrkern
-Prozessoren optimal nutzen zu können, eignet sich Go äußerst gut für große
-Programmierprojekte.
+Die Sprache Go (auch golang) wurde von Google entwickelt und wird seit 2007
+benutzt. Go ähnelt in der Syntax der Sprache C, bietet darüber hinaus aber viele
+Vorteile. Einerseits verzichtet Gp auf Speicherarithmetik und
+benutzt einen Garbabe Collector. Andererseits enthält Go native Sprachelemente
+für die Unterstützung von Nebenläufigkeit. Durch den Fokus auf einen schnellen
+Kompilierprozess wird außerdem die Softwareentwicklung in Großprojekten
+erleichtert.
Außerdem beinhaltet Go eine gut ausgestattete Standardbibliothek und hat eine
aktive Community.
@@ -24,8 +24,8 @@ aktive Community.
/* Mehr-
zeiliger Kommentar */
-// Eine jede Quelldatei beginnt mit einer Paket-Klausel.
-// "main" ist ein besonderer Pkaetname, da er ein ausführbares Programm
+// Wie bei Java gehört jede Quelldatei einem Paket an (Modularisierung).
+// "main" ist ein besonderer Paketname, da er ein ausführbares Programm
// einleitet, im Gegensatz zu jedem anderen Namen, der eine Bibliothek
// deklariert.
package main
@@ -38,9 +38,9 @@ import (
"strconv" // Zeichenkettenmanipulation
)
-// Es folgt die Definition einer Funktions, in diesem Fall von "main". Auch hier
+// Es folgt die Definition einer Funktion, in diesem Fall von "main". Auch hier
// ist der Name wieder besonders. "main" markiert den Eintrittspunkt des
-// Programms. Vergessen Sie nicht die geschweiften Klammern!
+// Programms.
func main() {
// Println gibt eine Zeile zu stdout aus.
// Der Prefix "fmt" bestimmt das Paket aus welchem die Funktion stammt.
@@ -50,13 +50,13 @@ func main() {
beyondHello()
}
-// Funktionen können Parameter akzeptieren, diese werden in Klammern deklariert,
-// die aber auch bei keinen Parametern erforderlich sind.
+// Funktionen können Parameter akzeptieren. Diese werden in Klammern deklariert,
+// die aber auch ohne Parameter erforderlich sind.
func beyondHello() {
var x int // Deklaration einer Variable, muss vor Gebrauch geschehen.
x = 3 // Zuweisung eines Werts.
// Kurze Deklaration: Benutzen Sie ":=", um die Typisierung automatisch zu
- // folgern, die Variable zu deklarieren und ihr einen Wert zu zuweisen.
+ // folgern, die Variable zu deklarieren und ihr einen Wert zuzuweisen.
y := 4
// Eine Funktion mit mehreren Rückgabewerten.
@@ -99,7 +99,7 @@ Zeilenumbrüche beinhalten.` // Selber Zeichenketten-Typ
// "slices" haben eine dynamische Größe. Arrays und Slices haben beide ihre
// Vorzüge, aber slices werden viel häufiger verwendet
s3 := []int{4, 5, 9} // Vergleichen Sie mit a3, hier: keine Ellipse
- s4 := make([]int, 4) // Weist Speicher für 4 ints zu, alle mit Initialwert 0
+ s4 := make([]int, 4) // Weist Speicher für 4 ints zu, alle mit Wert 0
var d2 [][]float64 // Nur eine Deklaration, keine Speicherzuweisung
bs := []byte("eine slice") // Umwandlungs-Syntax
@@ -147,7 +147,7 @@ func learnFlowControl() {
if false {
// nicht hier
} else {
- // sonder hier! spielt die Musik
+ // sondern hier! spielt die Musik
}
// Benutzen Sie ein "switch" Statement anstatt eine Anreihung von if-s
@@ -166,7 +166,7 @@ func learnFlowControl() {
// Ab hier gilt wieder: x == 1
// For ist die einzige Schleifenform in Go, sie hat aber mehrere Formen:
- for { // Endloschleife
+ for { // Endlosschleife
break // nur ein Spaß
continue // wird nie ausgeführt
}
@@ -201,7 +201,8 @@ type pair struct {
x, y int
}
-// Definiere eine Methode von "pair". Dieser Typ erfüllt jetzt das Stringer interface.
+// Definiere eine Methode von "pair".
+// Dieser Typ erfüllt jetzt das Stringer interface.
func (p pair) String() string { // p ist der Empfänger
// Sprintf ist eine weitere öffentliche Funktion von fmt.
// Der Syntax mit Punkt greift auf die Felder zu.
@@ -255,18 +256,19 @@ func learnConcurrency() {
// Die selbe "make"-Funktion wie vorhin. Sie initialisiert Speicher für
// maps, slices und Kanäle.
c := make(chan int)
- // Starte drei parallele "Goroutines". Die Zahlen werden parallel (concurrently)
- // erhöht. Alle drei senden ihr Ergebnis in den gleichen Kanal.
+ // Starte drei parallele "Goroutines".
+ // Die Zahlen werden parallel (concurrently) erhöht.
+ // Alle drei senden ihr Ergebnis in den gleichen Kanal.
go inc(0, c) // "go" ist das Statement zum Start einer neuen Goroutine
go inc(10, c)
go inc(-805, c)
// Auslesen und dann Ausgeben der drei berechneten Werte.
// Man kann nicht im voraus feststellen in welcher Reihenfolge die Werte
// ankommen.
- fmt.Println(<-c, <-c, <-c) // mit dem Kannal rechts ist <- der Empfangs-Operator
+ fmt.Println(<-c, <-c, <-c) // mit dem Kanal rechts ist <- der Empfangs-Operator
- cs := make(chan string) // ein weiterer Kannal, diesmal für strings
- cc := make(chan chan string) // ein Kannal für string Kannäle
+ cs := make(chan string) // ein weiterer Kanal, diesmal für strings
+ cc := make(chan chan string) // ein Kanal für string Kanäle
// Start einer neuen Goroutine, nur um einen Wert zu senden
go func() { c <- 84 }()
@@ -283,7 +285,7 @@ func learnConcurrency() {
fmt.Println("wird nicht passieren.")
}
// Hier wird eine der beiden Goroutines fertig sein, die andere nicht.
- // Sie wird warten bis der Wert den sie sendet von dem Kannal gelesen wird.
+ // Sie wird warten bis der Wert den sie sendet von dem Kanal gelesen wird.
learnWebProgramming() // Go kann es und Sie hoffentlich auch bald.
}
@@ -301,19 +303,18 @@ func learnWebProgramming() {
// Methode implementieren: ServeHTTP
func (p pair) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// Senden von Daten mit einer Methode des http.ResponseWriter
- w.Write([]byte("Sie habe Go in Y Minuten gelernt!"))
+ w.Write([]byte("Sie haben Go in Y Minuten gelernt!"))
}
```
## Weitere Resourcen
-Alles zu Go finden Sie auf der [offiziellen Go Webseite](http://golang.org/).
-Dort können sie dem Tutorial folgen, interaktiv Quelltext ausprobieren und viel
-Dokumentation lesen.
+Informationen zu Go findet man auf der [offiziellen Go Webseite](http://golang.org/).
+Dort gibt es unter anderem ein Tutorial und interaktive Quelltext-Beispiele, vor
+allem aber Dokumentation zur Sprache und den Paketen.
Auch zu empfehlen ist die Spezifikation von Go, die nach heutigen Standards sehr
-kurz und auch gut verständlich formuliert ist. Auf der Leseliste von Go-Neulingen
-ist außerdem der Quelltext der [Go standard Bibliothek](http://golang.org/src/pkg/).
-Gut dokumentiert, demonstriert sie leicht zu verstehendes und im idiomatischen Stil
-verfasstes Go. Erreichbar ist der Quelltext auch durch das Klicken der Funktionsnamen
+kurz und gut verständlich formuliert ist. Auf der Leseliste von Go-Neulingen
+ist außerdem der Quelltext der [Go standard Bibliothek](http://golang.org/src/pkg/)
+einzusehen. Dieser kann als Referenz für leicht zu verstehendes und im idiomatischen Stil
+verfasstes Go dienen. Erreichbar ist der Quelltext auch durch das Klicken der Funktionsnamen
in der [offiziellen Dokumentation von Go](http://golang.org/pkg/).
-
diff --git a/de-de/hack-de.html.markdown b/de-de/hack-de.html.markdown
new file mode 100644
index 00000000..42428130
--- /dev/null
+++ b/de-de/hack-de.html.markdown
@@ -0,0 +1,322 @@
+---
+language: Hack
+lang: de-de
+contributors:
+ - ["Stephen Holdaway", "https://github.com/stecman"]
+ - ["David Lima", "https://github.com/davelima"]
+translators:
+ - ["Jerome Meinke", "https://github.com/jmeinke"]
+filename: learnhack-de.hh
+---
+
+Hack ist eine von Facebook neu entwickelte Programmiersprache auf Basis von PHP.
+Sie wird von der HipHop Virtual Machine (HHVM) ausgeführt. Die HHVM kann
+aufgrund der Ähnlichkeit der Programmiersprachen nicht nur Hack, sondern auch
+PHP-Code ausführen. Der wesentliche Unterschied zu PHP besteht in der statischen
+Typisierung der Sprache, die eine wesentlich höhere Performance erlaubt.
+
+
+Hier werden nur Hack-spezifische Eigenschaften beschrieben. Details über PHP's
+Syntax findet man im [PHP Artikel](http://learnxinyminutes.com/docs/php/) dieser
+Seite.
+
+```php
+<?hh
+
+// Hack-Syntax ist nur für Dateien aktiv, die mit dem <?hh Prefix starten.
+// Der <?hh Prefix kann nicht wie <?php mit HTML gemischt werden.
+// Benutzung von "<?hh //strict" aktiviert den Strikt-Modus des Type-Checkers.
+
+
+// Typisierung für Funktions-Argumente
+function repeat(string $word, int $count)
+{
+ $word = trim($word);
+ return str_repeat($word . ' ', $count);
+}
+
+// Typisierung für Rückgabewerte
+function add(...$numbers) : int
+{
+ return array_sum($numbers);
+}
+
+// Funktionen ohne Rückgabewert, werden mit "void" typisiert
+function truncate(resource $handle) : void
+{
+ // ...
+}
+
+// Typisierung unterstützt die explizit optionale Ein- / Ausgabe von "null"
+function identity(?string $stringOrNull) : ?string
+{
+ return $stringOrNull;
+}
+
+// Typisierung von Klassen-Eigenschaften
+class TypeHintedProperties
+{
+ public ?string $name;
+
+ protected int $id;
+
+ private float $score = 100.0;
+
+ // Hack erfordert es, dass typisierte Eigenschaften (also "non-null")
+ // einen Default-Wert haben oder im Konstruktor initialisiert werden.
+ public function __construct(int $id)
+ {
+ $this->id = $id;
+ }
+}
+
+
+// Kurzgefasste anonyme Funktionen (lambdas)
+$multiplier = 5;
+array_map($y ==> $y * $multiplier, [1, 2, 3]);
+
+
+// Weitere, spezielle Felder (Generics)
+// Diese kann man sich als ein zugreifbares Interface vorstellen
+class Box<T>
+{
+ protected T $data;
+
+ public function __construct(T $data) {
+ $this->data = $data;
+ }
+
+ public function getData(): T {
+ return $this->data;
+ }
+}
+
+function openBox(Box<int> $box) : int
+{
+ return $box->getData();
+}
+
+
+// Formen
+//
+// Hack fügt das Konzept von Formen hinzu, wie struct-ähnliche arrays
+// mit einer typ-geprüften Menge von Schlüsseln
+type Point2D = shape('x' => int, 'y' => int);
+
+function distance(Point2D $a, Point2D $b) : float
+{
+ return sqrt(pow($b['x'] - $a['x'], 2) + pow($b['y'] - $a['y'], 2));
+}
+
+distance(
+ shape('x' => -1, 'y' => 5),
+ shape('x' => 2, 'y' => 50)
+);
+
+
+// Typen-Definition bzw. Aliasing
+//
+// Hack erlaubt es Typen zu definieren und sorgt somit für bessere Lesbarkeit
+newtype VectorArray = array<int, Vector<int>>;
+
+// Ein Tupel mit zwei Integern
+newtype Point = (int, int);
+
+function addPoints(Point $p1, Point $p2) : Point
+{
+ return tuple($p1[0] + $p2[0], $p1[1] + $p2[1]);
+}
+
+addPoints(
+ tuple(1, 2),
+ tuple(5, 6)
+);
+
+
+// Erstklassige Aufzählungen (enums)
+enum RoadType : int
+{
+ Road = 0;
+ Street = 1;
+ Avenue = 2;
+ Boulevard = 3;
+}
+
+function getRoadType() : RoadType
+{
+ return RoadType::Avenue;
+}
+
+
+// Automatische Erstellung von Klassen-Eigenschaften durch Konstruktor-Argumente
+//
+// Wiederkehrende Definitionen von Klassen-Eigenschaften können durch die Hack-
+// Syntax vermieden werden. Hack erlaubt es die Klassen-Eigenschaften über
+// Argumente des Konstruktors zu definieren.
+class ArgumentPromotion
+{
+ public function __construct(public string $name,
+ protected int $age,
+ private bool $isAwesome) {}
+}
+
+class WithoutArgumentPromotion
+{
+ public string $name;
+
+ protected int $age;
+
+ private bool $isAwesome;
+
+ public function __construct(string $name, int $age, bool $isAwesome)
+ {
+ $this->name = $name;
+ $this->age = $age;
+ $this->isAwesome = $isAwesome;
+ }
+}
+
+
+// Kooperatives Multitasking
+//
+// Die Schlüsselworte "async" and "await" führen Multitasking ein.
+// Achtung, hier werden keine Threads benutzt, sondern nur Aktivität getauscht.
+async function cooperativePrint(int $start, int $end) : Awaitable<void>
+{
+ for ($i = $start; $i <= $end; $i++) {
+ echo "$i ";
+
+ // Geben anderen Tasks die Möglichkeit aktiv zu werden
+ await RescheduleWaitHandle::create(RescheduleWaitHandle::QUEUE_DEFAULT, 0);
+ }
+}
+
+// Die Ausgabe von folgendem Code ist "1 4 7 2 5 8 3 6 9"
+AwaitAllWaitHandle::fromArray([
+ cooperativePrint(1, 3),
+ cooperativePrint(4, 6),
+ cooperativePrint(7, 9)
+])->getWaitHandle()->join();
+
+
+// Attribute
+//
+// Attribute repräsentieren eine Form von Metadaten für Funktionen.
+// Hack bietet Spezial-Attribute, die nützliche Eigenschaften mit sich bringen.
+
+// Das __Memoize Attribut erlaubt es die Ausgabe einer Funktion zu cachen.
+<<__Memoize>>
+function doExpensiveTask() : ?string
+{
+ return file_get_contents('http://example.com');
+}
+
+// Der Funktionsrumpf wird im Folgenden nur ein einziges mal ausgeführt:
+doExpensiveTask();
+doExpensiveTask();
+
+
+// Das __ConsistentConstruct Attribut signalisiert dem type-checker, dass
+// die Funktionsdeklaration von __construct für alle Unterklassen dieselbe ist.
+<<__ConsistentConstruct>>
+class ConsistentFoo
+{
+ public function __construct(int $x, float $y)
+ {
+ // ...
+ }
+
+ public function someMethod()
+ {
+ // ...
+ }
+}
+
+class ConsistentBar extends ConsistentFoo
+{
+ public function __construct(int $x, float $y)
+ {
+ // Der Type-checker erzwingt den Aufruf des Eltern-Klassen-Konstruktors
+ parent::__construct($x, $y);
+
+ // ...
+ }
+
+ // Das __Override Attribut ist ein optionales Signal an den Type-Checker,
+ // das erzwingt, dass die annotierte Methode die Methode der Eltern-Klasse
+ // oder des Traits verändert.
+ <<__Override>>
+ public function someMethod()
+ {
+ // ...
+ }
+}
+
+class InvalidFooSubclass extends ConsistentFoo
+{
+ // Wenn der Konstruktor der Eltern-Klasse nicht übernommen wird,
+ // wird der Type-Checker einen Fehler ausgeben:
+ //
+ // "This object is of type ConsistentBaz. It is incompatible with this object
+ // of type ConsistentFoo because some of their methods are incompatible"
+ //
+ public function __construct(float $x)
+ {
+ // ...
+ }
+
+ // Auch bei der Benutzung des __Override Attributs für eine nicht veränderte
+ // Methode wird vom Type-Checker eine Fehler ausgegeben:
+ //
+ // "InvalidFooSubclass::otherMethod() is marked as override; no non-private
+ // parent definition found or overridden parent is defined in non-<?hh code"
+ //
+ <<__Override>>
+ public function otherMethod()
+ {
+ // ...
+ }
+}
+
+// Ein Trait ist ein Begriff aus der objektorientierten Programmierung und
+// beschreibt eine wiederverwendbare Sammlung von Methoden und Attributen,
+// ähnlich einer Klasse.
+
+// Anders als in PHP können Traits auch als Schnittstellen (Interfaces)
+// implementiert werden und selbst Schnittstellen implementieren.
+interface KittenInterface
+{
+ public function play() : void;
+}
+
+trait CatTrait implements KittenInterface
+{
+ public function play() : void
+ {
+ // ...
+ }
+}
+
+class Samuel
+{
+ use CatTrait;
+}
+
+
+$cat = new Samuel();
+$cat instanceof KittenInterface === true; // True
+
+```
+
+## Weitere Informationen
+
+Die Hack [Programmiersprachen-Referenz](http://docs.hhvm.com/manual/de/hacklangref.php)
+erklärt die neuen Eigenschaften der Sprache detailliert auf Englisch. Für
+allgemeine Informationen kann man auch die offizielle Webseite [hacklang.org](http://hacklang.org/)
+besuchen.
+
+Die offizielle Webseite [hhvm.com](http://hhvm.com/) bietet Infos zum Download
+und zur Installation der HHVM.
+
+Hack's [nicht-untersützte PHP Syntax-Elemente](http://docs.hhvm.com/manual/en/hack.unsupported.php)
+werden im offiziellen Handbuch beschrieben.
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 &amp; 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/haskell-de.html.markdown b/de-de/haskell-de.html.markdown
index 2c548961..d1a0008e 100644
--- a/de-de/haskell-de.html.markdown
+++ b/de-de/haskell-de.html.markdown
@@ -5,6 +5,7 @@ contributors:
- ["Adit Bhargava", "http://adit.io"]
translators:
- ["Henrik Jürges", "https://github.com/santifa"]
+ - ["Nikolai Weh", "http://weh.hamburg"]
filename: haskell-de.hs
---
@@ -58,12 +59,13 @@ not False -- True
-- Strings und Zeichen
"Das ist ein String."
'a' -- Zeichen
-'Einfache Anfuehrungszeichen gehen nicht.' -- error!
+'Einfache Anführungszeichen gehen nicht.' -- error!
-- Strings können konkateniert werden.
"Hello " ++ "world!" -- "Hello world!"
-- Ein String ist eine Liste von Zeichen.
+['H', 'a', 'l', 'l', 'o', '!'] -- "Hallo!"
"Das ist eine String" !! 0 -- 'D'
@@ -76,11 +78,23 @@ not False -- True
[1, 2, 3, 4, 5]
[1..5]
--- Haskell unterstuetzt unendliche Listen!
-[1..] -- Die Liste aller natuerlichen Zahlen
+-- Die zweite Variante nennt sich die "range"-Syntax.
+-- Ranges sind recht flexibel:
+['A'..'F'] -- "ABCDEF"
+
+-- Es ist möglich eine Schrittweite anzugeben:
+[0,2..10] -- [0,2,4,6,8,10]
+[5..1] -- [], da Haskell standardmässig inkrementiert.
+[5,4..1] -- [5,4,3,2,1]
+
+-- Der "!!"-Operator extrahiert das Element an einem bestimmten Index:
+[1..10] !! 3 -- 4
+
+-- Haskell unterstützt unendliche Listen!
+[1..] -- Die Liste aller natürlichen Zahlen
-- Unendliche Listen funktionieren in Haskell, da es "lazy evaluation"
--- unterstuetzt. Haskell evaluiert erst etwas, wenn es benötigt wird.
+-- unterstützt. Haskell evaluiert erst etwas, wenn es benötigt wird.
-- Somit kannst du nach dem 1000. Element fragen und Haskell gibt es dir:
[1..] !! 999 -- 1000
@@ -92,12 +106,9 @@ not False -- True
-- Zwei Listen konkatenieren
[1..5] ++ [6..10]
--- Ein Element als Head hinzufuegen
+-- Ein Element als Head hinzufügen
0:[1..5] -- [0, 1, 2, 3, 4, 5]
--- Gibt den 5. Index zurueck
-[0..] !! 5 -- 5
-
-- Weitere Listenoperationen
head [1..5] -- 1
tail [1..5] -- [2, 3, 4, 5]
@@ -114,7 +125,8 @@ last [1..5] -- 5
-- Ein Tupel:
("haskell", 1)
--- Auf Elemente eines Tupels zugreifen:
+-- Ein Paar (Pair) ist ein Tupel mit 2 Elementen, auf die man wie folgt
+-- zugreifen kann:
fst ("haskell", 1) -- "haskell"
snd ("haskell", 1) -- 1
@@ -140,9 +152,9 @@ add 1 2 -- 3
(//) a b = a `div` b
35 // 4 -- 8
--- Guards sind eine einfache Möglichkeit fuer Fallunterscheidungen.
+-- Guards sind eine einfache Möglichkeit für Fallunterscheidungen.
fib x
- | x < 2 = x
+ | x < 2 = 1
| otherwise = fib (x - 1) + fib (x - 2)
-- Pattern Matching funktioniert ähnlich.
@@ -174,7 +186,7 @@ foldl1 (\acc x -> acc + x) [1..5] -- 15
-- 4. Mehr Funktionen
----------------------------------------------------
--- currying: Wenn man nicht alle Argumente an eine Funktion uebergibt,
+-- currying: Wenn man nicht alle Argumente an eine Funktion übergibt,
-- so wird sie eine neue Funktion gebildet ("curried").
-- Es findet eine partielle Applikation statt und die neue Funktion
-- nimmt die fehlenden Argumente auf.
@@ -190,23 +202,28 @@ foo 5 -- 15
-- Funktionskomposition
-- Die (.) Funktion verkettet Funktionen.
-- Zum Beispiel, die Funktion Foo nimmt ein Argument addiert 10 dazu und
--- multipliziert dieses Ergebnis mit 5.
-foo = (*5) . (+10)
+-- multipliziert dieses Ergebnis mit 4.
+foo = (*4) . (+10)
+
+-- (5 + 10) * 4 = 60
+foo 5 -- 60
--- (5 + 10) * 5 = 75
-foo 5 -- 75
+-- Haskell hat einen Operator `$`, welcher Funktionsapplikation durchführt.
+-- Im Gegenzug zu der Standard-Funktionsapplikation, welche linksassoziativ ist
+-- und die höchstmögliche Priorität von "10" hat, ist der `$`-Operator
+-- rechtsassoziativ und hat die Priorität 0. Dieses hat (idr.) den Effekt,
+-- dass der `komplette` Ausdruck auf der rechten Seite als Parameter für die
+-- Funktion auf der linken Seite verwendet wird.
+-- Mit `.` und `$` kann man sich so viele Klammern ersparen.
--- Haskell hat eine Funktion `$`. Diese ändert den Vorrang,
--- so dass alles links von ihr zuerst berechnet wird und
--- und dann an die rechte Seite weitergegeben wird.
--- Mit `.` und `$` kann man sich viele Klammern ersparen.
+(even (fib 7)) -- false
--- Vorher
-(even (fib 7)) -- true
+-- Äquivalent:
+even $ fib 7 -- false
--- Danach
-even . fib $ 7 -- true
+-- Funktionskomposition:
+even . fib $ 7 -- false
----------------------------------------------------
-- 5. Typensystem
@@ -221,31 +238,31 @@ even . fib $ 7 -- true
True :: Bool
-- Funktionen haben genauso Typen.
--- `not` ist Funktion die ein Bool annimmt und ein Bool zurueckgibt:
+-- `not` ist Funktion die ein Bool annimmt und ein Bool zurückgibt:
-- not :: Bool -> Bool
-- Eine Funktion die zwei Integer Argumente annimmt:
-- add :: Integer -> Integer -> Integer
-- Es ist guter Stil zu jeder Funktionsdefinition eine
--- Typdefinition darueber zu schreiben:
+-- Typdefinition darüber zu schreiben:
double :: Integer -> Integer
double x = x * 2
----------------------------------------------------
--- 6. If-Anweisung und Kontrollstrukturen
+-- 6. If-Ausdrücke und Kontrollstrukturen
----------------------------------------------------
--- If-Anweisung:
+-- If-Ausdruck:
haskell = if 1 == 1 then "awesome" else "awful" -- haskell = "awesome"
--- If-Anweisungen können auch ueber mehrere Zeilen verteilt sein.
--- Das Einruecken ist dabei äußerst wichtig.
+-- If-Ausdrücke können auch über mehrere Zeilen verteilt sein.
+-- Die Einrückung ist dabei wichtig.
haskell = if 1 == 1
then "awesome"
else "awful"
--- Case-Anweisung: Zum Beispiel "commandline" Argumente parsen.
+-- Case-Ausdruck: Am Beispiel vom Parsen von "commandline"-Argumenten.
case args of
"help" -> printHelp
"start" -> startProgram
@@ -276,7 +293,7 @@ foldl (\x y -> 2*x + y) 4 [1,2,3] -- 43
foldr (\x y -> 2*x + y) 4 [1,2,3] -- 16
-- die Abarbeitung sieht so aus:
-(2 * 3 + (2 * 2 + (2 * 1 + 4)))
+(2 * 1 + (2 * 2 + (2 * 3 + 4)))
----------------------------------------------------
-- 7. Datentypen
@@ -300,7 +317,7 @@ data Maybe a = Nothing | Just a
-- Diese sind alle vom Typ Maybe:
Just "hello" -- vom Typ `Maybe String`
Just 1 -- vom Typ `Maybe Int`
-Nothing -- vom Typ `Maybe a` fuer jedes `a`
+Nothing -- vom Typ `Maybe a` für jedes `a`
----------------------------------------------------
-- 8. Haskell IO
@@ -309,8 +326,8 @@ Nothing -- vom Typ `Maybe a` fuer jedes `a`
-- IO kann nicht völlig erklärt werden ohne Monaden zu erklären,
-- aber man kann die grundlegenden Dinge erklären.
--- Wenn eine Haskell Programm ausgefuehrt wird, so wird `main` aufgerufen.
--- Diese muss etwas vom Typ `IO ()` zurueckgeben. Zum Beispiel:
+-- Wenn eine Haskell Programm ausgeführt wird, so wird `main` aufgerufen.
+-- Diese muss etwas vom Typ `IO ()` zurückgeben. Zum Beispiel:
main :: IO ()
main = putStrLn $ "Hello, sky! " ++ (say Blue)
@@ -338,10 +355,10 @@ sayHello = do
-- an die Variable "name" gebunden
putStrLn $ "Hello, " ++ name
--- Uebung: Schreibe deine eigene Version von `interact`,
+-- Übung: Schreibe deine eigene Version von `interact`,
-- die nur eine Zeile einliest.
--- `sayHello` wird niemals ausgefuehrt, nur `main` wird ausgefuehrt.
+-- `sayHello` wird niemals ausgeführt, nur `main` wird ausgeführt.
-- Um `sayHello` laufen zulassen kommentiere die Definition von `main`
-- aus und ersetze sie mit:
-- main = sayHello
@@ -359,7 +376,7 @@ action = do
input1 <- getLine
input2 <- getLine
-- Der Typ von `do` ergibt sich aus der letzten Zeile.
- -- `return` ist eine Funktion und keine Schluesselwort
+ -- `return` ist eine Funktion und keine Schlüsselwort
return (input1 ++ "\n" ++ input2) -- return :: String -> IO String
-- Nun können wir `action` wie `getLine` benutzen:
@@ -370,7 +387,7 @@ main'' = do
putStrLn result
putStrLn "This was all, folks!"
--- Der Typ `IO` ist ein Beispiel fuer eine Monade.
+-- Der Typ `IO` ist ein Beispiel für eine Monade.
-- Haskell benutzt Monaden Seiteneffekte zu kapseln und somit
-- eine rein funktional Sprache zu sein.
-- Jede Funktion die mit der Außenwelt interagiert (z.B. IO)
@@ -387,7 +404,7 @@ main'' = do
-- Starte die REPL mit dem Befehl `ghci`
-- Nun kann man Haskell Code eingeben.
--- Alle neuen Werte muessen mit `let` gebunden werden:
+-- Alle neuen Werte müssen mit `let` gebunden werden:
let foo = 5
@@ -396,7 +413,7 @@ let foo = 5
>:t foo
foo :: Integer
--- Auch jede `IO ()` Funktion kann ausgefuehrt werden.
+-- Auch jede `IO ()` Funktion kann ausgeführt werden.
> sayHello
What is your name?
@@ -420,6 +437,6 @@ qsort (p:xs) = qsort lesser ++ [p] ++ qsort greater
Haskell ist sehr einfach zu installieren.
Hohl es dir von [hier](http://www.haskell.org/platform/).
-Eine sehr viele langsamere Einfuehrung findest du unter:
+Eine sehr viele langsamere Einführung findest du unter:
[Learn you a Haskell](http://learnyouahaskell.com/) oder
[Real World Haskell](http://book.realworldhaskell.org/).
diff --git a/de-de/latex-de.html.markdown b/de-de/latex-de.html.markdown
index 2c18b8fd..ee9c6e3e 100644
--- a/de-de/latex-de.html.markdown
+++ b/de-de/latex-de.html.markdown
@@ -6,19 +6,19 @@ contributors:
- ["Sricharan Chiruvolu", "http://sricharan.xyz"]
translators:
- ["Moritz Kammerer", "https://github.com/phxql"]
+ - ["Jerome Meinke", "https://github.com/jmeinke"]
lang: de-de
filename: latex-de.tex
---
```
-% Alle Kommentare starten fangen mit % an
-% Es gibt keine Kommentare über mehrere Zeilen
+% Alle Kommentare starten mit einem Prozentzeichen %
-% LateX ist keine "What You See Is What You Get" Textverarbeitungssoftware wie z.B.
+% LaTeX ist keine "What You See Is What You Get" Textverarbeitungssoftware wie z.B.
% MS Word oder OpenOffice Writer
-% Jedes LateX-Kommando startet mit einem Backslash (\)
+% Jedes LaTeX-Kommando startet mit einem Backslash (\)
-% LateX-Dokumente starten immer mit der Definition des Dokuments, die sie darstellen
+% LaTeX-Dokumente starten immer mit der Definition des Dokuments, die sie darstellen
% Weitere Dokumententypen sind z.B. book, report, presentations, etc.
% Optionen des Dokuments stehen zwischen den eckigen Klammern []. In diesem Fall
% wollen wir einen 12 Punkte-Font verwenden.
@@ -26,7 +26,7 @@ filename: latex-de.tex
% Als nächstes definieren wir die Pakete, die wir verwenden wollen.
% Wenn du z.B. Grafiken, farbigen Text oder Quelltext in dein Dokument einbetten möchtest,
-% musst du die Fähigkeiten von Latex durch Hinzufügen von Paketen erweitern.
+% musst du die Fähigkeiten von LaTeX durch Hinzufügen von Paketen erweitern.
% Wir verwenden die Pakete float und caption für Bilder.
\usepackage{caption}
\usepackage{float}
@@ -34,30 +34,41 @@ filename: latex-de.tex
% Mit diesem Paket können leichter Umlaute getippt werden
\usepackage[utf8]{inputenc}
+% Es gibt eigentlich keine Kommentare über mehrere Zeilen, solche kann man
+% aber selbst durch die Angabe eigener Kommandos definieren.
+% Dieses Kommando kann man später benutzen.
+\newcommand{\comment}[1]{}
+
% Es können durchaus noch weitere Optione für das Dokument gesetzt werden!
\author{Chaitanya Krishna Ande, Colton Kohnke \& Sricharan Chiruvolu}
\date{\today}
-\title{Learn LaTeX in Y Minutes!}
+\title{Learn \LaTeX\ in Y Minutes!}
% Nun kann's losgehen mit unserem Dokument.
% Alles vor dieser Zeile wird die Preamble genannt.
-\begin{document}
+\begin{document}
+
+\comment{
+ Dies ist unser selbst-definierter Befehl
+ für mehrzeilige Kommentare.
+}
+
% Wenn wir den Autor, das Datum und den Titel gesetzt haben, kann
-% LateX für uns eine Titelseite generieren
+% LaTeX für uns eine Titelseite generieren
\maketitle
-% Die meisten Paper haben ein Abstract. LateX bietet dafür einen vorgefertigen Befehl an.
+% Die meisten Paper haben ein Abstract. LaTeX bietet dafür einen vorgefertigen Befehl an.
% Das Abstract sollte in der logischen Reihenfolge, also nach dem Titel, aber vor dem
% Inhalt erscheinen.
% Dieser Befehl ist in den Dokumentenklassen article und report verfügbar.
\begin{abstract}
- LateX documentation geschrieben in LateX! Wie ungewöhnlich und garantiert nicht meine Idee!
+ \LaTeX -Documentation geschrieben in \LaTeX ! Wie ungewöhnlich und garantiert nicht meine Idee!
\end{abstract}
% Section Befehle sind intuitiv.
% Alle Titel der sections werden automatisch in das Inhaltsverzeichnis übernommen.
\section{Einleitung}
-Hi, mein Name ist Moritz und zusammen werden wir LateX erforschen!
+Hi, mein Name ist Moritz und zusammen werden wir \LaTeX\ erforschen!
\section{Noch eine section}
Das hier ist der Text für noch eine section. Ich glaube, wir brauchen eine subsection.
@@ -71,16 +82,16 @@ So ist's schon viel besser.
% Wenn wir den Stern nach section schreiben, dann unterdrückt LateX die Nummerierung.
% Das funktioniert auch bei anderen Befehlen.
-\section*{Das ist eine unnummerierte section}
-Es müssen nicht alle sections nummeriert sein!
+\section*{Das ist eine unnummerierte section}
+Es müssen nicht alle Sections nummeriert sein!
\section{Ein paar Notizen}
-LateX ist ziemlich gut darin, Text so zu platzieren, dass es gut aussieht.
+\LaTeX\ ist ziemlich gut darin, Text so zu platzieren, dass es gut aussieht.
Falls eine Zeile \\ mal \\ woanders \\ umgebrochen \\ werden \\ soll, füge
\textbackslash\textbackslash in den Code ein.\\
\section{Listen}
-Listen sind eine der einfachsten Dinge in LateX. Ich muss morgen einkaufen gehen,
+Listen sind eine der einfachsten Dinge in \LaTeX. Ich muss morgen einkaufen gehen,
also lass uns eine Einkaufsliste schreiben:
\begin{enumerate} % Dieser Befehl erstellt eine "enumerate" Umgebung.
% \item bringt enumerate dazu, eins weiterzuzählen.
@@ -96,7 +107,7 @@ also lass uns eine Einkaufsliste schreiben:
\section{Mathe}
-Einer der Haupteinsatzzwecke von LateX ist das Schreiben von akademischen
+Einer der Haupteinsatzzwecke von \LaTeX\ ist das Schreiben von akademischen
Artikeln oder Papern. Meistens stammen diese aus dem Bereich der Mathe oder
anderen Wissenschaften. Und deswegen müssen wir in der Lage sein, spezielle
Symbole zu unserem Paper hinzuzufügen! \\
@@ -106,18 +117,18 @@ Symbole für Mengen und relationen, Pfeile, Operatoren und Griechische Buchstabe
um nur ein paar zu nennen.\\
Mengen und Relationen spielen eine sehr wichtige Rolle in vielen mathematischen
-Papern. So schreibt man in LateX, dass alle y zu X gehören: $\forall$ y $\in$ X. \\
+Papern. So schreibt man in \LaTeX, dass alle y zu X gehören: $\forall$ y $\in$ X. \\
-% Achte auf die $ Zeichen vor und nach den Symbolen. Wenn wir in LateX schreiben,
+% Achte auf die $ Zeichen vor und nach den Symbolen. Wenn wir in LaTeX schreiben,
% geschieht dies standardmäßig im Textmodus. Die Mathe-Symbole existieren allerdings
% nur im Mathe-Modus. Wir können den Mathe-Modus durch das $ Zeichen aktivieren und
% ihn mit $ wieder verlassen. Variablen können auch im Mathe-Modus angezeigt werden.
Mein Lieblingsbuchstabe im Griechischen ist $\xi$. Ich mag auch $\beta$, $\gamma$ und $\sigma$.
-Bis jetzt habe ich noch keinen griechischen Buchstaben gefunden, den LateX nicht kennt!
+Bis jetzt habe ich noch keinen griechischen Buchstaben gefunden, den \LaTeX nicht kennt!
Operatoren sind ebenfalls wichtige Bestandteile von mathematischen Dokumenten:
-Trigonometrische Funktionen ($\sin$, $\cos$, $\tan$),
+Trigonometrische Funktionen ($\sin$, $\cos$, $\tan$),
Logarithmus und Exponenten ($\log$, $\exp$),
Grenzwerte ($\lim$), etc. haben vordefinierte Befehle.
Lass uns eine Gleichung schreiben: \\
@@ -127,7 +138,7 @@ $\cos(2\theta) = \cos^{2}(\theta) - \sin^{2}(\theta)$\\
Brüche (Zähler / Nenner) können so geschrieben werden:
% 10 / 7
-$^{10}/_{7}$
+$^{10}/_{7}$
% Komplexere Brüche können so geschrieben werden:
% \frac{Zähler}{Nenner}
@@ -142,19 +153,19 @@ Wir können Gleichungen auch in einer equation Umgebung verwenden.
\end{equation} % Alle \begin Befehle müssen einen \end Befehl besitzen
Wir können nun unsere Gleichung referenzieren!
-Gleichung ~\ref{eq:pythagoras} ist auch als das Theorem des Pythagoras bekannt. Dieses wird in
+Gleichung ~\ref{eq:pythagoras} ist auch als das Theorem des Pythagoras bekannt. Dieses wird in
Abschnitt ~\ref{subsec:pythagoras} behandelt. Es können sehr viele Sachen mit Labels versehen werden:
Grafiken, Gleichungen, Sections, etc.
Summen und Integrale können mit den sum und int Befehlen dargestellt werden:
-% Manche LateX-Compiler beschweren sich, wenn Leerzeilen in Gleichungen auftauchen
-\begin{equation}
+% Manche LaTeX-Compiler beschweren sich, wenn Leerzeilen in Gleichungen auftauchen
+\begin{equation}
\sum_{i=0}^{5} f_{i}
-\end{equation}
-\begin{equation}
+\end{equation}
+\begin{equation}
\int_{0}^{\infty} \mathrm{e}^{-x} \mathrm{d}x
-\end{equation}
+\end{equation}
\section{Grafiken}
@@ -164,7 +175,7 @@ Aber keine Sorge, ich muss auch jedes mal nachschauen, welche Option wie wirkt.
\begin{figure}[H] % H ist die Platzierungsoption
\centering % Zentriert die Grafik auf der Seite
% Fügt eine Grafik ein, die auf 80% der Seitenbreite einnimmt.
- %\includegraphics[width=0.8\linewidth]{right-triangle.png}
+ %\includegraphics[width=0.8\linewidth]{right-triangle.png}
% Auskommentiert, damit es nicht im Dokument auftaucht.
\caption{Dreieck mit den Seiten $a$, $b$, $c$}
\label{fig:right-triangle}
@@ -177,7 +188,7 @@ Wir können Tabellen genauso wie Grafiken einfügen.
\caption{Überschrift der Tabelle.}
% Die {} Argumente geben an, wie eine Zeile der Tabelle dargestellt werden soll.
% Auch hier muss ich jedes Mal nachschauen. Jedes. einzelne. Mal.
- \begin{tabular}{c|cc}
+ \begin{tabular}{c|cc}
Nummer & Nachname & Vorname \\ % Spalten werden durch & getrennt
\hline % Eine horizontale Linie
1 & Biggus & Dickus \\
@@ -187,36 +198,36 @@ Wir können Tabellen genauso wie Grafiken einfügen.
% \section{Links} % Kommen bald!
-\section{Verhindern, dass LateX etwas kompiliert (z.B. Quelltext)}
-Angenommen, wir wollen Quelltext in unserem LateX-Dokument. LateX soll
-in diesem Fall nicht den Quelltext als LateX-Kommandos interpretieren,
+\section{Verhindern, dass \LaTeX\ etwas kompiliert (z.B. Quelltext)}
+Angenommen, wir wollen Quelltext in unserem \LaTeX-Dokument. \LaTeX\ soll
+in diesem Fall nicht den Quelltext als \LaTeX-Kommandos interpretieren,
sondern es einfach ins Dokument schreiben. Um das hinzubekommen, verwenden
wir eine verbatim Umgebung.
% Es gibt noch weitere Pakete für Quelltexte (z.B. minty, lstlisting, etc.)
% aber verbatim ist das simpelste.
-\begin{verbatim}
+\begin{verbatim}
print("Hello World!")
a%b; % Schau dir das an! Wir können % im verbatim verwenden!
random = 4; #decided by fair random dice roll
\end{verbatim}
-\section{Kompilieren}
+\section{Kompilieren}
Ich vermute, du wunderst dich, wie du dieses tolle Dokument in ein PDF
verwandeln kannst. (Ja, dieses Dokument kompiliert wirklich!) \\
Dafür musst du folgende Schritte durchführen:
\begin{enumerate}
- \item Schreibe das Dokument. (den LateX-Quelltext).
- \item Kompiliere den Quelltext in ein PDF.
+ \item Schreibe das Dokument. (den \LaTeX -Quelltext).
+ \item Kompiliere den Quelltext in ein PDF.
Das Kompilieren sieht so ähnlich wie das hier aus (Linux): \\
- \begin{verbatim}
- $pdflatex learn-latex.tex learn-latex.pdf
+ \begin{verbatim}
+ $pdflatex learn-latex.tex learn-latex.pdf
\end{verbatim}
\end{enumerate}
-Manche LateX-Editoren kombinieren Schritt 1 und 2. Du siehst also nur Schritt 1 und Schritt
+Manche \LaTeX-Editoren kombinieren Schritt 1 und 2. Du siehst also nur Schritt 1 und Schritt
2 wird unsichtbar im Hintergrund ausgeführt.
Alle Formatierungsoptionen werden in Schritt 1 in den Quelltext geschrieben. Schritt 2 verwendet
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/make-de.html.markdown b/de-de/make-de.html.markdown
new file mode 100644
index 00000000..22c14a69
--- /dev/null
+++ b/de-de/make-de.html.markdown
@@ -0,0 +1,260 @@
+---
+language: make
+contributors:
+ - ["Robert Steed", "https://github.com/robochat"]
+translators:
+ - ["Martin Schimandl", "https://github.com/Git-Jiro"]
+filename: Makefile-de
+lang: de-de
+---
+
+Eine Makefile definiert einen Graphen von Regeln um ein Ziel (oder Ziele)
+zu erzeugen. Es dient dazu die geringste Menge an Arbeit zu verrichten um
+ein Ziel in einklang mit dem Quellcode zu bringen. Make wurde berühmterweise
+von Stuart Feldman 1976 übers Wochenende geschrieben. Make ist noch immer
+sehr verbreitet (vorallem im Unix umfeld) obwohl es bereits sehr viel
+Konkurrenz und Kritik zu Make gibt.
+
+Es gibt eine vielzahl an Varianten von Make, dieser Artikel beschäftig sich
+mit der Version GNU Make. Diese Version ist standard auf Linux.
+
+```make
+
+# Kommentare können so geschrieben werden.
+
+# Dateien sollten Makefile heißen, denn dann können sie als `make <ziel>`
+# aufgerufen werden. Ansonsten muss `make -f "dateiname" <ziel>` verwendet
+# werden.
+
+# Warnung - Es sollten nur TABULATOREN zur Einrückung im Makefile verwendet
+# werden. Niemals Leerzeichen!
+
+#-----------------------------------------------------------------------
+# Grundlagen
+#-----------------------------------------------------------------------
+
+# Eine Regel - Diese Regel wird nur abgearbeitet wenn die Datei file0.txt
+# nicht existiert.
+file0.txt:
+ echo "foo" > file0.txt
+ # Selbst Kommentare in der 'Rezept' Sektion werden an die Shell
+ # weitergegeben. Versuche `make file0.txt` oder einfach `make`
+ # die erste Regel ist die Standard-Regel.
+
+
+# Diese Regel wird nur abgearbeitet wenn file0.txt aktueller als file1.txt ist.
+file1.txt: file0.txt
+ cat file0.txt > file1.txt
+ # Verwende die selben Quoting-Regeln wie die Shell
+ @cat file0.txt >> file1.txt
+ # @ unterdrückt die Ausgabe des Befehls an stdout.
+ -@echo 'hello'
+ # - bedeutet das Make die Abarbeitung fortsetzt auch wenn Fehler passieren.
+ # Versuche `make file1.txt` auf der Kommandozeile.
+
+# Eine Regel kann mehrere Ziele und mehrere Voraussetzungen haben.
+file2.txt file3.txt: file0.txt file1.txt
+ touch file2.txt
+ touch file3.txt
+
+# Make wird sich beschweren wenn es mehrere Rezepte für die gleiche Regel gibt.
+# Leere Rezepte zählen nicht und können dazu verwendet werden weitere
+# Voraussetzungen hinzuzufügen.
+
+#-----------------------------------------------------------------------
+# Phony-Ziele
+#-----------------------------------------------------------------------
+
+# Ein Phony-Ziel ist ein Ziel das keine Datei ist.
+# Es wird nie aktuell sein, daher wird Make immer versuchen es abzuarbeiten
+all: maker process
+
+# Es ist erlaubt Dinge ausserhalb der Reihenfolge zu deklarieren.
+maker:
+ touch ex0.txt ex1.txt
+
+# Um das Fehlschlagen von Phony-Regeln zu vermeiden wenn eine echte Datei den
+# selben namen wie ein Phony-Ziel hat:
+.PHONY: all maker process
+# Das ist ein spezielles Ziel. Es gibt noch ein paar mehr davon.
+
+# Eine Regel mit einem Phony-Ziel als Voraussetzung wird immer abgearbeitet
+ex0.txt ex1.txt: maker
+
+# Häufige Phony-Ziele sind: all make clean install ...
+
+#-----------------------------------------------------------------------
+# Automatische Variablen & Wildcards
+#-----------------------------------------------------------------------
+
+process: file*.txt # Eine Wildcard um Dateinamen zu Vergleichen
+ @echo $^ # $^ ist eine Variable die eine Liste aller
+ # Voraussetzungen enthält.
+ @echo $@ # Namen des Ziels ausgeben.
+ #(Bei mehreren Ziel-Regeln enthält $@ den Verursacher der Abarbeitung
+ #der Regel.)
+ @echo $< # Die erste Voraussetzung aus der Liste
+ @echo $? # Nur die Voraussetzungen die nicht aktuell sind.
+ @echo $+ # Alle Voraussetzungen inklusive Duplikate (nicht wie Üblich)
+ #@echo $| # Alle 'order only' Voraussetzungen
+
+# Selbst wenn wir die Voraussetzungen der Regel aufteilen, $^ wird sie finden.
+process: ex1.txt file0.txt
+# ex1.txt wird gefunden werden, aber file0.txt wird dedupliziert.
+
+#-----------------------------------------------------------------------
+# Muster
+#-----------------------------------------------------------------------
+
+# Mit Mustern kann man make beibringen wie Dateien in andere Dateien
+# umgewandelt werden.
+
+%.png: %.svg
+ inkscape --export-png $^
+
+# Muster-Vergleichs-Regeln werden nur abgearbeitet wenn make entscheidet das Ziel zu
+# erzeugen
+
+# Verzeichnis-Pfade werden normalerweise bei Muster-Vergleichs-Regeln ignoriert.
+# Aber make wird versuchen die am besten passende Regel zu verwenden.
+small/%.png: %.svg
+ inkscape --export-png --export-dpi 30 $^
+
+# Make wird die letzte Version einer Muster-Vergleichs-Regel verwenden die es
+# findet.
+%.png: %.svg
+ @echo this rule is chosen
+
+# Allerdings wird make die erste Muster-Vergleicher-Regel verwenden die das
+# Ziel erzeugen kann.
+%.png: %.ps
+ @echo this rule is not chosen if *.svg and *.ps are both present
+
+# Make hat bereits ein paar eingebaute Muster-Vergleichs-Regelen. Zum Beispiel
+# weiß Make wie man aus *.c Dateien *.o Dateien erzeugt.
+
+# Ältere Versionen von Make verwenden möglicherweise Suffix-Regeln anstatt
+# Muster-Vergleichs-Regeln.
+.png.ps:
+ @echo this rule is similar to a pattern rule.
+
+# Aktivieren der Suffix-Regel
+.SUFFIXES: .png
+
+#-----------------------------------------------------------------------
+# Variablen
+#-----------------------------------------------------------------------
+# auch Makros genannt.
+
+# Variablen sind im Grunde genommen Zeichenketten-Typen.
+
+name = Ted
+name2="Sarah"
+
+echo:
+ @echo $(name)
+ @echo ${name2}
+ @echo $name # Das funktioniert nicht, wird als $(n)ame behandelt.
+ @echo $(name3) # Unbekannte Variablen werden als leere Zeichenketten behandelt.
+
+# Es git 4 Stellen um Variablen zu setzen.
+# In Reihenfolge der Priorität von höchster zu niedrigster:
+# 1: Befehls-Zeilen Argumente
+# 2: Makefile
+# 3: Shell Umbebungs-Variablen - Make importiert diese automatisch.
+# 3: MAke hat einige vordefinierte Variablen.
+
+name4 ?= Jean
+# Setze die Variable nur wenn es eine gleichnamige Umgebungs-Variable noch
+# nicht gibt.
+
+override name5 = David
+# Verhindert das Kommando-Zeilen Argumente diese Variable ändern können.
+
+name4 +=grey
+# Werte an eine Variable anhängen (inkludiert Leerzeichen).
+
+# Muster-Spezifische Variablen Werte (GNU Erweiterung).
+echo: name2 = Sara # Wahr innerhalb der passenden Regel und auch innerhalb
+ # rekursiver Voraussetzungen (ausser wenn es den Graphen zerstören
+ # kann wenn es zu kompilizert wird!)
+
+# Ein paar Variablen die von Make automatisch definiert werden.
+echo_inbuilt:
+ echo $(CC)
+ echo ${CXX)}
+ echo $(FC)
+ echo ${CFLAGS)}
+ echo $(CPPFLAGS)
+ echo ${CXXFLAGS}
+ echo $(LDFLAGS)
+ echo ${LDLIBS}
+
+#-----------------------------------------------------------------------
+# Variablen 2
+#-----------------------------------------------------------------------
+
+# Der erste Typ von Variablen wird bei jeder verwendung ausgewertet.
+# Das kann aufwendig sein, daher exisitert ein zweiter Typ von Variablen.
+# Diese werden nur einmal ausgewertet. (Das ist eine GNU make Erweiterung)
+
+var := hello
+var2 ::= $(var) hello
+#:= und ::= sind äquivalent.
+
+# Diese Variablen werden prozedural ausgwertet (in der Reihenfolge in der sie
+# auftauchen), die stehen daher im wiederspruch zum Rest der Sprache!
+
+# Das funktioniert nicht
+var3 ::= $(var4) and good luck
+var4 ::= good night
+
+#-----------------------------------------------------------------------
+# Funktionen
+#-----------------------------------------------------------------------
+
+# Make verfügt über eine vielzahl von Funktionen.
+
+sourcefiles = $(wildcard *.c */*.c)
+objectfiles = $(patsubst %.c,%.o,$(sourcefiles))
+
+# Das Format ist $(func arg0,arg1,arg2...)
+
+# Ein paar Beispiele
+ls: * src/*
+ @echo $(filter %.txt, $^)
+ @echo $(notdir $^)
+ @echo $(join $(dir $^),$(notdir $^))
+
+#-----------------------------------------------------------------------
+# Direktiven
+#-----------------------------------------------------------------------
+
+# Inkludiere andere Makefile, sehr praktisch für platformspezifischen Code
+include foo.mk
+
+sport = tennis
+# Konditionale kompiliereung
+report:
+ifeq ($(sport),tennis)
+ @echo 'game, set, match'
+else
+ @echo "They think it's all over; it is now"
+endif
+
+# Es gibt auch ifneq, ifdef, ifndef
+
+foo = true
+
+ifdef $(foo)
+bar = 'hello'
+endif
+```
+
+
+### Mehr Resourcen
+
++ [gnu make documentation](https://www.gnu.org/software/make/manual/)
++ [software carpentry tutorial](http://swcarpentry.github.io/make-novice/)
++ learn C the hard way [ex2](http://c.learncodethehardway.org/book/ex2.html) [ex28](http://c.learncodethehardway.org/book/ex28.html)
+
diff --git a/de-de/markdown-de.html.markdown b/de-de/markdown-de.html.markdown
index 6a90980b..2c838660 100644
--- a/de-de/markdown-de.html.markdown
+++ b/de-de/markdown-de.html.markdown
@@ -56,7 +56,7 @@ __Genau wie dieser.__
**_Dieser auch!_**
*__Und dieser genau so!__*
-<!-- In "Github Flavored Markdown", dem von Github verwendeten Dialekt / Parser,
+<!-- In "GitHub Flavored Markdown", dem von GitHub verwendeten Dialekt / Parser,
gibt es auch noch durchgestrichenen Text: -->
~~Dieser Text wird durchgestrichen dargestellt.~~
@@ -148,7 +148,7 @@ indem du eine Zeile mit vier Leerzeichen oder einem Tabulator einrückst -->
Hermann hatte nicht die leiseste Ahnung, was dieses `go_to()` bedeuten könnte!
-<!-- In "Github Flavored Markdown" gibt es für Code nocheinmal eine
+<!-- In "GitHub Flavored Markdown" gibt es für Code nocheinmal eine
besondere Syntax -->
\`\`\`ruby <!-- in "echt" musst du die Backslashes entfernen: ```ruby ! -->
@@ -157,7 +157,7 @@ def foobar
end
\`\`\` <!-- hier auch keine Backslashes, nur ``` -->
-<-- der obige Block muss nicht extra eingerückt werden, außerdem fügt Github
+<-- der obige Block muss nicht extra eingerückt werden, außerdem fügt GitHub
Syntax-Highlighting für die nach dem ``` angegebene Sprache hinzu -->
<!-- Horizontale Linie (<hr />) -->
@@ -233,7 +233,7 @@ Ich würde *diesen Teil gerne mit Sternen umschließen*, doch ohne dass er kursi
wird. Also mache ich folgendes: \*Ich umschließe diesen Text mit Sternen\*!
<!-- Tabellen -->
-<!-- Tabellen gibt es bis jetzt nur in "Github Flavored Markdown".
+<!-- Tabellen gibt es bis jetzt nur in "GitHub Flavored Markdown".
Zudem sind sie ziemlich mühselig, aber wenn du es wirklich wissen willst: -->
| Spalte1 | Spalte2 | Spalte3 |
@@ -253,4 +253,4 @@ Ganz schön hässlich | vielleicht doch lieber | wieder aufhören
Mehr Informationen gibt es in [John Gruber's offiziellem Blog-Post](http://daringfireball.net/projects/markdown/syntax)
und bei Adam Pritchards [grandiosem Cheatsheet](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet).
-Infos zu Github Flavored Markdown [gibt es hier](https://help.github.com/articles/github-flavored-markdown). \ No newline at end of file
+Infos zu GitHub Flavored Markdown [gibt es hier](https://help.github.com/articles/github-flavored-markdown). \ No newline at end of file
diff --git a/de-de/scala-de.html.markdown b/de-de/scala-de.html.markdown
index 7fd299b4..456403a2 100644
--- a/de-de/scala-de.html.markdown
+++ b/de-de/scala-de.html.markdown
@@ -5,6 +5,7 @@ contributors:
- ["Dominic Bou-Samra", "http://dbousamra.github.com"]
- ["Geoff Liu", "http://geoffliu.me"]
- ["Ha-Duong Nguyen", "http://reference-error.org"]
+ - ["Dennis Keller", "github.com/denniskeller"]
translators:
- ["Christian Albrecht", "https://github.com/coastalchief"]
filename: learnscala-de.scala
@@ -16,167 +17,172 @@ für die Java Virtual Machine (JVM), um allgemeine Programmieraufgaben
zu erledigen. Scala hat einen akademischen Hintergrund und wurde an
der EPFL (Lausanne / Schweiz) unter der Leitung von Martin Odersky entwickelt.
-
-# 0. Umgebung einrichten
+```scala
+/*
Scala Umgebung einrichten:
1. Scala binaries herunterladen- http://www.scala-lang.org/downloads
2. Unzip/untar in ein Verzeichnis
3. das bin Unterverzeichnis der `PATH` Umgebungsvariable hinzufügen
4. Mit dem Kommando `scala` wird die REPL gestartet und zeigt als Prompt:
-```
+
scala>
-```
Die REPL (Read-Eval-Print Loop) ist der interaktive Scala Interpreter.
Hier kann man jeden Scala Ausdruck verwenden und das Ergebnis wird direkt
ausgegeben.
Als nächstes beschäftigen wir uns mit ein paar Scala Basics.
+*/
-# 1. Basics
-Einzeilige Kommentare beginnen mit zwei vorwärts Slash
+/////////////////////////////////////////////////
+// 1. Basics
+/////////////////////////////////////////////////
+
+// Einzeilige Kommentare beginnen mit zwei Slashes
/*
- Mehrzeilige Kommentare, werden starten
- mit Slash-Stern und enden mit Stern-Slash
+ Mehrzeilige Kommentare, starten
+ mit einem Slash-Stern und enden mit einem Stern-Slash
*/
// Einen Wert, und eine zusätzliche neue Zeile ausgeben
-```
+
println("Hello world!")
println(10)
-```
+
// Einen Wert, ohne eine zusätzliche neue Zeile ausgeben
-```
+
print("Hello world")
-```
-// Variablen werden entweder mit var oder val deklariert.
-// Deklarationen mit val sind immutable, also unveränderlich
-// Deklarationen mit var sind mutable, also veränderlich
-// Immutability ist gut.
-```
+/*
+ Variablen werden entweder mit var oder val deklariert.
+ Deklarationen mit val sind immutable, also unveränderlich
+ Deklarationen mit var sind mutable, also veränderlich
+ Immutability ist gut.
+*/
val x = 10 // x ist 10
x = 20 // error: reassignment to val
var y = 10
y = 20 // y ist jetzt 20
-```
-Scala ist eine statisch getypte Sprache, auch wenn in dem o.g. Beispiel
+/*
+Scala ist eine statisch getypte Sprache, auch wenn wir in dem o.g. Beispiel
keine Typen an x und y geschrieben haben.
-In Scala ist etwas eingebaut, was sich Type Inference nennt. D.h. das der
-Scala Compiler in den meisten Fällen erraten kann, von welchen Typ eine ist,
-so dass der Typ nicht jedes mal angegeben werden soll.
+In Scala ist etwas eingebaut, was sich Type Inference nennt. Das heißt das der
+Scala Compiler in den meisten Fällen erraten kann, von welchen Typ eine Variable ist,
+so dass der Typ nicht jedes mal angegeben werden muss.
Einen Typ gibt man bei einer Variablendeklaration wie folgt an:
-```
+*/
val z: Int = 10
val a: Double = 1.0
-```
+
// Bei automatischer Umwandlung von Int auf Double wird aus 10 eine 10.0
-```
+
val b: Double = 10
-```
+
// Boolean Werte
-```
+
true
false
-```
+
// Boolean Operationen
-```
+
!true // false
!false // true
true == false // false
10 > 5 // true
-```
+
// Mathematische Operationen sind wie gewohnt
-```
+
1 + 1 // 2
2 - 1 // 1
5 * 3 // 15
6 / 2 // 3
6 / 4 // 1
6.0 / 4 // 1.5
-```
+
// Die Auswertung eines Ausdrucks in der REPL gibt den Typ
// und das Ergebnis zurück.
-```
+
scala> 1 + 7
res29: Int = 8
-```
+/*
Das bedeutet, dass das Resultat der Auswertung von 1 + 7 ein Objekt
von Typ Int ist und einen Wert 0 hat.
"res29" ist ein sequentiell generierter name, um das Ergebnis des
Ausdrucks zu speichern. Dieser Wert kann bei Dir anders sein...
-
+*/
"Scala strings werden in doppelten Anführungszeichen eingeschlossen"
'a' // A Scala Char
// 'Einzeln ge-quotete strings gibt es nicht!' <= This causes an error
// Für Strings gibt es die üblichen Java Methoden
-```
+
"hello world".length
"hello world".substring(2, 6)
"hello world".replace("C", "3")
-```
+
// Zusätzlich gibt es noch extra Scala Methoden
// siehe: scala.collection.immutable.StringOps
-```
+
"hello world".take(5)
"hello world".drop(5)
-```
+
// String interpolation: prefix "s"
-```
+
val n = 45
s"We have $n apples" // => "We have 45 apples"
-```
-// Ausdrücke im innern von interpolierten Strings gibt es auch
-```
+
+// Ausdrücke im Innern von interpolierten Strings gibt es auch
+
val a = Array(11, 9, 6)
val n = 100
s"My second daughter is ${a(0) - a(2)} years old." // => "My second daughter is 5 years old."
s"We have double the amount of ${n / 2.0} in apples." // => "We have double the amount of 22.5 in apples."
s"Power of 2: ${math.pow(2, 2)}" // => "Power of 2: 4"
-```
+
// Formatierung der interpolierten Strings mit dem prefix "f"
-```
+
f"Power of 5: ${math.pow(5, 2)}%1.0f" // "Power of 5: 25"
f"Square root of 122: ${math.sqrt(122)}%1.4f" // "Square root of 122: 11.0454"
-```
+
// Raw Strings, ignorieren Sonderzeichen.
-```
+
raw"New line feed: \n. Carriage return: \r." // => "New line feed: \n. Carriage return: \r."
-```
+
// Manche Zeichen müssen "escaped" werden, z.B.
// ein doppeltes Anführungszeichen in innern eines Strings.
-```
+
"They stood outside the \"Rose and Crown\"" // => "They stood outside the "Rose and Crown""
-```
+
// Dreifache Anführungszeichen erlauben es, dass ein String über mehrere Zeilen geht
// und Anführungszeichen enthalten kann.
-```
+
val html = """<form id="daform">
<p>Press belo', Joe</p>
<input type="submit">
</form>"""
-```
-# 2. Funktionen
+
+/////////////////////////////////////////////////
+// 2. Funktionen
+/////////////////////////////////////////////////
// Funktionen werden so definiert
//
@@ -184,74 +190,74 @@ val html = """<form id="daform">
//
// Beachte: Es gibt kein return Schlüsselwort. In Scala ist der letzte Ausdruck
// in einer Funktion der Rückgabewert.
-```
+
def sumOfSquares(x: Int, y: Int): Int = {
val x2 = x * x
val y2 = y * y
x2 + y2
}
-```
+
// Die geschweiften Klammern können weggelassen werden, wenn
// die Funktion nur aus einem einzigen Ausdruck besteht:
-```
+
def sumOfSquaresShort(x: Int, y: Int): Int = x * x + y * y
-```
+
// Syntax für Funktionsaufrufe:
-```
+
sumOfSquares(3, 4) // => 25
-```
+
// In den meisten Fällen (mit Ausnahme von rekursiven Funktionen), können
// Rückgabetypen auch weggelassen werden, da dieselbe Typ Inference, wie bei
// Variablen, auch bei Funktionen greift:
-```
+
def sq(x: Int) = x * x // Compiler errät, dass der return type Int ist
-```
+
// Funktionen können default parameter haben:
-```
+
def addWithDefault(x: Int, y: Int = 5) = x + y
addWithDefault(1, 2) // => 3
addWithDefault(1) // => 6
-```
+
// Anonyme Funktionen sehen so aus:
-```
+
(x: Int) => x * x
-```
+
// Im Gegensatz zu def bei normalen Funktionen, kann bei anonymen Funktionen
// sogar der Eingabetyp weggelassen werden, wenn der Kontext klar ist.
// Beachte den Typ "Int => Int", dies beschreibt eine Funktion,
// welche Int als Parameter erwartet und Int zurückgibt.
-```
+
val sq: Int => Int = x => x * x
-```
+
// Anonyme Funktionen benutzt man ganz normal:
-```
+
sq(10) // => 100
-```
+
// Wenn ein Parameter einer anonymen Funktion nur einmal verwendet wird,
// bietet Scala einen sehr kurzen Weg diesen Parameter zu benutzen,
// indem die Parameter als Unterstrich "_" in der Parameterreihenfolge
// verwendet werden. Diese anonymen Funktionen werden sehr häufig
// verwendet.
-```
+
val addOne: Int => Int = _ + 1
val weirdSum: (Int, Int) => Int = (_ * 2 + _ * 3)
addOne(5) // => 6
weirdSum(2, 4) // => 16
-```
+
// Es gibt einen keyword return in Scala. Allerdings ist seine Verwendung
// nicht immer ratsam und kann fehlerbehaftet sein. "return" gibt nur aus
// dem innersten def, welches den return Ausdruck umgibt, zurück.
// "return" hat keinen Effekt in anonymen Funktionen:
-```
+
def foo(x: Int): Int = {
val anonFunc: Int => Int = { z =>
if (z > 5)
@@ -261,28 +267,30 @@ def foo(x: Int): Int = {
}
anonFunc(x) // Zeile ist der return Wert von foo
}
-```
-# 3. Flow Control
-## Wertebereiche und Schleifen
-```
+/////////////////////////////////////////////////
+// 3. Flow Control
+/////////////////////////////////////////////////
+
+// Wertebereiche und Schleifen
+
1 to 5
val r = 1 to 5
r.foreach(println)
r foreach println
(5 to 1 by -1) foreach (println)
-```
-// Scala ist syntaktisch sehr grosszügig, Semikolons am Zeilenende
+
+// Scala ist syntaktisch sehr großzügig, Semikolons am Zeilenende
// sind optional, beim Aufruf von Methoden können die Punkte
// und Klammern entfallen und Operatoren sind im Grunde austauschbare Methoden
// while Schleife
-```
+
var i = 0
while (i < 10) { println("i " + i); i += 1 }
i // i ausgeben, res3: Int = 10
-```
+
// Beachte: while ist eine Schleife im klassischen Sinne -
// Sie läuft sequentiell ab und verändert die loop-Variable.
@@ -291,28 +299,28 @@ i // i ausgeben, res3: Int = 10
// und zu parellelisieren.
// Ein do while Schleife
-```
+
do {
println("x ist immer noch weniger wie 10")
x += 1
} while (x < 10)
-```
+
// Endrekursionen sind ideomatisch um sich wiederholende
// Dinge in Scala zu lösen. Rekursive Funtionen benötigen explizit einen
// return Typ, der Compiler kann ihn nicht erraten.
// Unit, in diesem Beispiel.
-```
+
def showNumbersInRange(a: Int, b: Int): Unit = {
print(a)
if (a < b)
showNumbersInRange(a + 1, b)
}
showNumbersInRange(1, 14)
-```
-## Conditionals
-```
+
+// Conditionals
+
val x = 10
if (x == 1) println("yeah")
if (x == 10) println("yeah")
@@ -320,186 +328,193 @@ if (x == 11) println("yeah")
if (x == 11) println ("yeah") else println("nay")
println(if (x == 10) "yeah" else "nope")
val text = if (x == 10) "yeah" else "nope"
-```
-# 4. Daten Strukturen (Array, Map, Set, Tuples)
-## Array
-```
+/////////////////////////////////////////////////
+// 4. Daten Strukturen (Array, Map, Set, Tuples)
+/////////////////////////////////////////////////
+
+// Array
+
val a = Array(1, 2, 3, 5, 8, 13)
a(0)
a(3)
a(21) // Exception
-```
-## Map - Speichert Key-Value-Paare
-```
+
+// Map - Speichert Key-Value-Paare
+
val m = Map("fork" -> "tenedor", "spoon" -> "cuchara", "knife" -> "cuchillo")
m("fork")
m("spoon")
m("bottle") // Exception
val safeM = m.withDefaultValue("no lo se")
safeM("bottle")
-```
-## Set - Speichert Unikate, unsortiert (sortiert -> SortedSet)
-```
+
+// Set - Speichert Unikate, unsortiert (sortiert -> SortedSet)
+
val s = Set(1, 3, 7)
s(0) //false
s(1) //true
val s = Set(1,1,3,3,7)
s: scala.collection.immutable.Set[Int] = Set(1, 3, 7)
-```
-## Tuple - Speichert beliebige Daten und "verbindet" sie miteinander
+
+// Tuple - Speichert beliebige Daten und "verbindet" sie miteinander
// Ein Tuple ist keine Collection.
-```
+
(1, 2)
(4, 3, 2)
(1, 2, "three")
(a, 2, "three")
-```
+
// Hier ist der Rückgabewert der Funktion ein Tuple
// Die Funktion gibt das Ergebnis, so wie den Rest zurück.
-```
+
val divideInts = (x: Int, y: Int) => (x / y, x % y)
divideInts(10, 3)
-```
+
// Um die Elemente eines Tuples anzusprechen, benutzt man diese
// Notation: _._n wobei n der index des Elements ist (Index startet bei 1)
-```
+
val d = divideInts(10, 3)
d._1
d._2
-```
-# 5. Objekt Orientierte Programmierung
-Bislang waren alle gezeigten Sprachelemente einfache Ausdrücke, welche zwar
-zum Ausprobieren und Lernen in der REPL gut geeignet sind, jedoch in
-einem Scala file selten alleine zu finden sind.
-Die einzigen Top-Level Konstrukte in Scala sind nämlich:
-- Klassen (classes)
-- Objekte (objects)
-- case classes
-- traits
+/////////////////////////////////////////////////
+// 5. Objektorientierte Programmierung
+/////////////////////////////////////////////////
+
+/*
+ Bislang waren alle gezeigten Sprachelemente einfache Ausdrücke, welche zwar
+ zum Ausprobieren und Lernen in der REPL gut geeignet sind, jedoch in
+ einem Scala file selten alleine zu finden sind.
+ Die einzigen Top-Level Konstrukte in Scala sind nämlich:
+
+ - Klassen (classes)
+ - Objekte (objects)
+ - case classes
+ - traits
-Diesen Sprachelemente wenden wir uns jetzt zu.
+ Diesen Sprachelemente wenden wir uns jetzt zu.
+*/
-## Klassen
+// Klassen
// Zum Erstellen von Objekten benötigt man eine Klasse, wie in vielen
// anderen Sprachen auch.
// erzeugt Klasse mit default Konstruktor
-```
+
class Hund
scala> val t = new Hund
t: Hund = Hund@7103745
-```
+
// Der Konstruktor wird direkt hinter dem Klassennamen deklariert.
-```
+
class Hund(sorte: String)
scala> val t = new Hund("Dackel")
t: Hund = Hund@14be750c
scala> t.sorte //error: value sorte is not a member of Hund
-```
+
// Per val wird aus dem Attribut ein unveränderliches Feld der Klasse
// Per var wird aus dem Attribut ein veränderliches Feld der Klasse
-```
+
class Hund(val sorte: String)
scala> val t = new Hund("Dackel")
t: Hund = Hund@74a85515
scala> t.sorte
res18: String = Dackel
-```
+
// Methoden werden mit def geschrieben
-```
+
def bark = "Woof, woof!"
-```
+
// Felder und Methoden können public, protected und private sein
// default ist public
// private ist nur innerhalb des deklarierten Bereichs sichtbar
-```
+
class Hund {
private def x = ...
def y = ...
}
-```
+
// protected ist nur innerhalb des deklarierten und aller
// erbenden Bereiche sichtbar
-```
+
class Hund {
protected def x = ...
}
class Dackel extends Hund {
// x ist sichtbar
}
-```
-## Object
-Wird ein Objekt ohne das Schlüsselwort "new" instanziert, wird das sog.
-"companion object" aufgerufen. Mit dem "object" Schlüsselwort wird so
-ein Objekt (Typ UND Singleton) erstellt. Damit kann man dann eine Klasse
-benutzen ohne ein Objekt instanziieren zu müssen.
-Ein gültiges companion Objekt einer Klasse ist es aber erst dann, wenn
-es genauso heisst und in derselben Datei wie die Klasse definiert wurde.
-```
+
+// Object
+// Wird ein Objekt ohne das Schlüsselwort "new" instanziert, wird das sog.
+// "companion object" aufgerufen. Mit dem "object" Schlüsselwort wird so
+// ein Objekt (Typ UND Singleton) erstellt. Damit kann man dann eine Klasse
+// benutzen ohne ein Objekt instanziieren zu müssen.
+// Ein gültiges companion Objekt einer Klasse ist es aber erst dann, wenn
+// es genauso heisst und in derselben Datei wie die Klasse definiert wurde.
+
object Hund {
def alleSorten = List("Pitbull", "Dackel", "Retriever")
def createHund(sorte: String) = new Hund(sorte)
}
-```
-## Case classes
-Fallklassen bzw. Case classes sind Klassen die normale Klassen um extra
-Funktionalität erweitern. Mit Case Klassen bekommt man ein paar
-Dinge einfach dazu, ohne sich darum kümmern zu müssen. Z.B.
-ein companion object mit den entsprechenden Methoden,
-Hilfsmethoden wie toString(), equals() und hashCode() und auch noch
-Getter für unsere Attribute (das Angeben von val entfällt dadurch)
-```
+
+// Case classes
+// Fallklassen bzw. Case classes sind Klassen die normale Klassen um extra
+// Funktionalität erweitern. Mit Case Klassen bekommt man ein paar
+// Dinge einfach dazu, ohne sich darum kümmern zu müssen. Z.B.
+// ein companion object mit den entsprechenden Methoden,
+// Hilfsmethoden wie toString(), equals() und hashCode() und auch noch
+// Getter für unsere Attribute (das Angeben von val entfällt dadurch)
+
class Person(val name: String)
class Hund(val sorte: String, val farbe: String, val halter: Person)
-```
+
// Es genügt das Schlüsselwort case vor die Klasse zu schreiben.
-```
+
case class Person(name: String)
case class Hund(sorte: String, farbe: String, halter: Person)
-```
+
// Für neue Instanzen brauch man kein "new"
-```
+
val dackel = Hund("dackel", "grau", Person("peter"))
val dogge = Hund("dogge", "grau", Person("peter"))
-```
+
// getter
-```
+
dackel.halter // => Person = Person(peter)
-```
+
// equals
-```
+
dogge == dackel // => false
-```
+
// copy
// otherGeorge == Person("george", "9876")
-```
+
val otherGeorge = george.copy(phoneNumber = "9876")
-```
-## Traits
-Ähnlich wie Java interfaces, definiert man mit traits einen Objekttyp
-und Methodensignaturen. Scala erlaubt allerdings das teilweise
-implementieren dieser Methoden. Konstruktorparameter sind nicht erlaubt.
-Traits können von anderen Traits oder Klassen erben, aber nur von
-parameterlosen.
-```
+
+// Traits
+// Ähnlich wie Java interfaces, definiert man mit traits einen Objekttyp
+// und Methodensignaturen. Scala erlaubt allerdings das teilweise
+// implementieren dieser Methoden. Konstruktorparameter sind nicht erlaubt.
+// Traits können von anderen Traits oder Klassen erben, aber nur von
+// parameterlosen.
+
trait Hund {
def sorte: String
def farbe: String
@@ -511,9 +526,9 @@ class Bernhardiner extends Hund{
val farbe = "braun"
def beissen = false
}
-```
+
-```
+
scala> b
res0: Bernhardiner = Bernhardiner@3e57cd70
scala> b.sorte
@@ -522,10 +537,10 @@ scala> b.bellen
res2: Boolean = true
scala> b.beissen
res3: Boolean = false
-```
+
// Traits können auch via Mixins (Schlüsselwort "with") eingebunden werden
-```
+
trait Bellen {
def bellen: String = "Woof"
}
@@ -541,25 +556,27 @@ scala> val b = new Bernhardiner
b: Bernhardiner = Bernhardiner@7b69c6ba
scala> b.bellen
res0: String = Woof
-```
-# 6. Pattern Matching
-Pattern matching in Scala ist ein sehr nützliches und wesentlich
-mächtigeres Feature als Vergleichsfunktionen in Java. In Scala
-benötigt ein case Statement kein "break", ein fall-through gibt es nicht.
-Mehrere Überprüfungen können mit einem Statement gemacht werden.
-Pattern matching wird mit dem Schlüsselwort "match" gemacht.
-```
+/////////////////////////////////////////////////
+// 6. Pattern Matching
+/////////////////////////////////////////////////
+
+// Pattern matching in Scala ist ein sehr nützliches und wesentlich
+// mächtigeres Feature als Vergleichsfunktionen in Java. In Scala
+// benötigt ein case Statement kein "break", ein fall-through gibt es nicht.
+// Mehrere Überprüfungen können mit einem Statement gemacht werden.
+// Pattern matching wird mit dem Schlüsselwort "match" gemacht.
+
val x = ...
x match {
case 2 =>
case 3 =>
case _ =>
}
-```
+
// Pattern Matching kann auf beliebige Typen prüfen
-```
+
val any: Any = ...
val gleicht = any match {
case 2 | 3 | 5 => "Zahl"
@@ -568,19 +585,19 @@ val gleicht = any match {
case 45.35 => "Double"
case _ => "Unbekannt"
}
-```
+
// und auf Objektgleichheit
-```
+
def matchPerson(person: Person): String = person match {
case Person("George", nummer) => "George! Die Nummer ist " + number
case Person("Kate", nummer) => "Kate! Die Nummer ist " + nummer
case Person(name, nummer) => "Irgendjemand: " + name + ", Telefon: " + nummer
}
-```
+
// Und viele mehr...
-```
+
val email = "(.*)@(.*)".r // regex
def matchEverything(obj: Any): String = obj match {
// Werte:
@@ -600,18 +617,21 @@ def matchEverything(obj: Any): String = obj match {
// Patterns kann man ineinander schachteln:
case List(List((1, 2, "YAY"))) => "Got a list of list of tuple"
}
-```
+
// Jedes Objekt mit einer "unapply" Methode kann per Pattern geprüft werden
// Ganze Funktionen können Patterns sein
-```
+
val patternFunc: Person => String = {
case Person("George", number) => s"George's number: $number"
case Person(name, number) => s"Random person's number: $number"
}
-```
-# 7. Higher-order functions
+
+/////////////////////////////////////////////////
+// 37. Higher-order functions
+/////////////////////////////////////////////////
+
Scala erlaubt, das Methoden und Funktion wiederum Funtionen und Methoden
als Aufrufparameter oder Return Wert verwenden. Diese Methoden heissen
higher-order functions
@@ -621,116 +641,117 @@ Nennenswerte sind:
"filter", "map", "reduce", "foldLeft"/"foldRight", "exists", "forall"
## List
-```
+
def isGleichVier(a:Int) = a == 4
val list = List(1, 2, 3, 4)
val resultExists4 = list.exists(isEqualToFour)
-```
+
## map
// map nimmt eine Funktion und führt sie auf jedem Element aus und erzeugt
// eine neue Liste
// Funktion erwartet ein Int und returned ein Int
-```
+
val add10: Int => Int = _ + 10
-```
+
// add10 wird auf jedes Element angewendet
-```
+
List(1, 2, 3) map add10 // => List(11, 12, 13)
-```
+
// Anonyme Funktionen können anstatt definierter Funktionen verwendet werden
-```
+
List(1, 2, 3) map (x => x + 10)
-```
+
// Der Unterstrich wird anstelle eines Parameters einer anonymen Funktion
// verwendet. Er wird an die Variable gebunden.
-```
+
List(1, 2, 3) map (_ + 10)
-```
+
// Wenn der anonyme Block und die Funtion beide EIN Argument erwarten,
// kann sogar der Unterstrich weggelassen werden.
-```
+
List("Dom", "Bob", "Natalia") foreach println
-```
-## filter
+
+// filter
// filter nimmt ein Prädikat (eine Funktion von A -> Boolean) und findet
// alle Elemente die auf das Prädikat passen
-```
+
List(1, 2, 3) filter (_ > 2) // => List(3)
case class Person(name: String, age: Int)
List(
Person(name = "Dom", age = 23),
Person(name = "Bob", age = 30)
).filter(_.age > 25) // List(Person("Bob", 30))
-```
-## reduce
+
+// reduce
// reduce nimmt zwei Elemente und kombiniert sie zu einem Element,
// und zwar solange bis nur noch ein Element da ist.
-## foreach
+// foreach
// foreach gibt es für einige Collections
-```
+
val aListOfNumbers = List(1, 2, 3, 4, 10, 20, 100)
aListOfNumbers foreach (x => println(x))
aListOfNumbers foreach println
-```
-## For comprehensions
+
+// For comprehensions
// Eine for-comprehension definiert eine Beziehung zwischen zwei Datensets.
// Dies ist keine for-Schleife.
-```
+
for { n <- s } yield sq(n)
val nSquared2 = for { n <- s } yield sq(n)
for { n <- nSquared2 if n < 10 } yield n
for { n <- s; nSquared = n * n if nSquared < 10} yield nSquared
-```
+
/////////////////////////////////////////////////
-# 8. Implicits
+// 8. Implicits
/////////////////////////////////////////////////
-**ACHTUNG:**
-Implicits sind ein sehr mächtiges Sprachfeature von Scala. Es sehr einfach
-sie falsch zu benutzen und Anfänger sollten sie mit Vorsicht oder am
-besten erst dann benutzen, wenn man versteht wie sie funktionieren.
-Dieses Tutorial enthält Implicits, da sie in Scala an jeder Stelle
-vorkommen und man auch mit einer Lib die Implicits benutzt nichts sinnvolles
-machen kann.
-Hier soll ein Grundverständnis geschaffen werden, wie sie funktionieren.
+// **ACHTUNG:**
+// Implicits sind ein sehr mächtiges Sprachfeature von Scala.
+// Es sehr einfach
+// sie falsch zu benutzen und Anfänger sollten sie mit Vorsicht oder am
+// besten erst dann benutzen, wenn man versteht wie sie funktionieren.
+// Dieses Tutorial enthält Implicits, da sie in Scala an jeder Stelle
+// vorkommen und man auch mit einer Lib die Implicits benutzt nichts sinnvolles
+// machen kann.
+// Hier soll ein Grundverständnis geschaffen werden, wie sie funktionieren.
// Mit dem Schlüsselwort implicit können Methoden, Werte, Funktion, Objekte
// zu "implicit Methods" werden.
-```
+
implicit val myImplicitInt = 100
implicit def myImplicitFunction(sorte: String) = new Hund("Golden " + sorte)
-```
+
// implicit ändert nicht das Verhalten eines Wertes oder einer Funktion
-```
+
myImplicitInt + 2 // => 102
myImplicitFunction("Pitbull").sorte // => "Golden Pitbull"
-```
+
// Der Unterschied ist, dass diese Werte ausgewählt werden können, wenn ein
// anderer Codeteil einen implicit Wert benötigt, zum Beispiel innerhalb von
// implicit Funktionsparametern
// Diese Funktion hat zwei Parameter: einen normalen und einen implicit
-```
+
def sendGreetings(toWhom: String)(implicit howMany: Int) =
s"Hello $toWhom, $howMany blessings to you and yours!"
-```
+
// Werden beide Parameter gefüllt, verhält sich die Funktion wie erwartet
-```
+
sendGreetings("John")(1000) // => "Hello John, 1000 blessings to you and yours!"
-```
+
// Wird der implicit Parameter jedoch weggelassen, wird ein anderer
// implicit Wert vom gleichen Typ genommen. Der Compiler sucht im
@@ -739,66 +760,69 @@ sendGreetings("John")(1000) // => "Hello John, 1000 blessings to you and yours!
// geforderten Typ konvertieren kann.
// Hier also: "myImplicitInt", da ein Int gesucht wird
-```
+
sendGreetings("Jane") // => "Hello Jane, 100 blessings to you and yours!"
-```
+
// bzw. "myImplicitFunction"
// Der String wird erst mit Hilfe der Funktion in Hund konvertiert, und
// dann wird die Methode aufgerufen
-```
+
"Retriever".sorte // => "Golden Retriever"
-```
-# 9. Misc
-## Importe
-```
+
+/////////////////////////////////////////////////
+// 19. Misc
+/////////////////////////////////////////////////
+// Importe
+
import scala.collection.immutable.List
-```
+
// Importiere alle Unterpackages
-```
+
import scala.collection.immutable._
-```
+
// Importiere verschiedene Klassen mit einem Statement
-```
+
import scala.collection.immutable.{List, Map}
-```
+
// Einen Import kann man mit '=>' umbenennen
-```
+
import scala.collection.immutable.{List => ImmutableList}
-```
+
// Importiere alle Klasses, mit Ausnahem von....
// Hier ohne: Map and Set:
-```
+
import scala.collection.immutable.{Map => _, Set => _, _}
-```
-## Main
-```
+
+// Main
+
object Application {
def main(args: Array[String]): Unit = {
- // stuff goes here.
+ // Sachen kommen hierhin
}
}
-```
-## I/O
+
+// I/O
// Eine Datei Zeile für Zeile lesen
-```
+
import scala.io.Source
for(line <- Source.fromFile("myfile.txt").getLines())
println(line)
-```
+
// Eine Datei schreiben
-```
+
val writer = new PrintWriter("myfile.txt")
writer.write("Schreibe Zeile" + util.Properties.lineSeparator)
writer.write("Und noch eine Zeile" + util.Properties.lineSeparator)
writer.close()
+
```
## Weiterführende Hinweise
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)
diff --git a/de-de/yaml-de.html.markdown b/de-de/yaml-de.html.markdown
index 19ea9e87..a46c30f6 100644
--- a/de-de/yaml-de.html.markdown
+++ b/de-de/yaml-de.html.markdown
@@ -30,7 +30,7 @@ null_Wert: null
Schlüssel mit Leerzeichen: value
# Strings müssen nicht immer mit Anführungszeichen umgeben sein, können aber:
jedoch: "Ein String in Anführungzeichen"
-"Ein Schlüssel in Anführungszeichen": "Nützlich, wenn du einen Doppelpunkt im Schluessel haben willst."
+"Ein Schlüssel in Anführungszeichen": "Nützlich, wenn du einen Doppelpunkt im Schlüssel haben willst."
# Mehrzeilige Strings schreibst du am besten als 'literal block' (| gefolgt vom Text)
# oder ein 'folded block' (> gefolgt vom text).
@@ -64,7 +64,7 @@ eine_verschachtelte_map:
hallo: hallo
# Schlüssel müssen nicht immer String sein.
-0.25: ein Float-Wert als Schluessel
+0.25: ein Float-Wert als Schlüssel
# Schlüssel können auch mehrzeilig sein, ? symbolisiert den Anfang des Schlüssels
? |