summaryrefslogtreecommitdiffhomepage
path: root/de-de
diff options
context:
space:
mode:
authorDmitrii Kuznetsov <torgeek@gmail.com>2021-02-22 18:42:33 +0300
committerDmitrii Kuznetsov <torgeek@gmail.com>2021-02-22 18:42:33 +0300
commite09fefaa3e78c645c720c86391e3f96d257be8a9 (patch)
tree0ff8b235e3e707125e2b11d5268ad085832355cb /de-de
parentf4c740839d78f797e9cbcfa1eb0483ac0ea45501 (diff)
parentbc8bd2646f068cfb402850f7c0f9b1dbfe81e5a0 (diff)
Merge branch 'master' of https://github.com/torgeek/learnxinyminutes-docs
Diffstat (limited to 'de-de')
-rw-r--r--de-de/LOLCODE-de.html.markdown188
-rw-r--r--de-de/asciidoc-de.html.markdown10
-rw-r--r--de-de/bash-de.html.markdown6
-rw-r--r--de-de/bc.html.markdown102
-rw-r--r--de-de/c++-de.html.markdown1158
-rw-r--r--de-de/c-de.html.markdown869
-rw-r--r--de-de/clojure-macros-de.html.markdown161
-rw-r--r--de-de/css-de.html.markdown6
-rw-r--r--de-de/d-de.html.markdown64
-rw-r--r--de-de/dhall-de.html.markdown380
-rw-r--r--de-de/dynamic-programming-de.html.markdown77
-rw-r--r--de-de/edn-de.html.markdown112
-rw-r--r--de-de/elm-de.html.markdown376
-rw-r--r--de-de/git-de.html.markdown20
-rw-r--r--de-de/go-de.html.markdown2
-rw-r--r--de-de/hq9+-de.html.markdown43
-rw-r--r--de-de/html-de.html.markdown20
-rw-r--r--de-de/java-de.html.markdown6
-rw-r--r--de-de/javascript-de.html.markdown4
-rw-r--r--de-de/latex-de.html.markdown8
-rw-r--r--de-de/make-de.html.markdown53
-rw-r--r--de-de/markdown-de.html.markdown6
-rw-r--r--de-de/nix-de.html.markdown358
-rw-r--r--de-de/opencv-de.html.markdown153
-rw-r--r--de-de/paren-de.html.markdown200
-rw-r--r--de-de/perl-de.html.markdown4
-rw-r--r--de-de/processing-de.html.markdown498
-rw-r--r--de-de/pug-de.html.markdown208
-rw-r--r--de-de/pyqt-de.html.markdown89
-rw-r--r--de-de/python-de.html.markdown306
-rw-r--r--de-de/python3-de.html.markdown655
-rw-r--r--de-de/pythonlegacy-de.html.markdown766
-rw-r--r--de-de/qt-de.html.markdown175
-rw-r--r--de-de/rst-de.html.markdown119
-rw-r--r--de-de/ruby-de.html.markdown782
-rw-r--r--de-de/scala-de.html.markdown582
-rw-r--r--de-de/shutit-de.html.markdown330
-rw-r--r--de-de/swift-de.html.markdown32
-rw-r--r--de-de/vim-de.html.markdown282
-rw-r--r--de-de/yaml-de.html.markdown6
40 files changed, 7724 insertions, 1492 deletions
diff --git a/de-de/LOLCODE-de.html.markdown b/de-de/LOLCODE-de.html.markdown
new file mode 100644
index 00000000..57eb0ff8
--- /dev/null
+++ b/de-de/LOLCODE-de.html.markdown
@@ -0,0 +1,188 @@
+---
+language: LOLCODE
+filename: learnLOLCODE-de.lol
+contributors:
+ - ["abactel", "https://github.com/abactel"]
+translators:
+ - ["Henrik Jürges", "http://github.com/santifa"]
+lang: de-de
+---
+
+LOLCODE ist eine esoterische Programmiersprache die die Sprache der [lolcats](https://upload.wikimedia.org/wikipedia/commons/a/ab/Lolcat_in_folder.jpg?1493656347257) nachahmt.
+
+```
+BTW Das ist ein Kommentar
+BTW Das Programm muss mit `HAI <language version>` beginnen und mit `KTHXBYE` enden.
+
+HAI 1.3
+CAN HAS STDIO? BTW Standard Header importieren
+
+OBTW
+ ==========================================================================
+ ============================== Grundlegendes =============================
+ ==========================================================================
+TLDR
+
+BTW Texte anzeigen:
+VISIBLE "HELLO WORLD"
+
+BTW Variablen deklarieren:
+I HAS A MESSAGE ITZ "CATZ ARE GOOD"
+VISIBLE MESSAGE
+
+OBTW
+ Variablen sind dynamisch typisiert und der Typ muss nicht explizit
+ angegeben werden. Die möglichen Typen sind:
+TLDR
+
+I HAS A STRING ITZ "DOGZ ARE GOOOD" BTW Typ ist YARN
+I HAS A INTEGER ITZ 42 BTW Typ ist NUMBR
+I HAS A FLOAT ITZ 3.1415 BTW Typ ist NUMBAR
+I HAS A BOOLEAN ITZ WIN BTW Typ ist TROOF
+I HAS A UNTYPED BTW Typ ist NOOB
+
+BTW Eingaben von Nutzern:
+I HAS A AGE
+GIMMEH AGE
+BTW Die Variable wird als YARN gespeichert und kann in eine
+BTW NUMBR konvertiert werden:
+AGE IS NOW A NUMBR
+
+OBTW
+ ==========================================================================
+ ================================== MATHE =================================
+ ==========================================================================
+TLDR
+
+BTW LOLCODE benutzt polnische Notation für Mathe.
+
+BTW grundlegende mathematische Notationen:
+
+SUM OF 21 AN 33 BTW 21 + 33
+DIFF OF 90 AN 10 BTW 90 - 10
+PRODUKT OF 12 AN 13 BTW 12 * 13
+QUOSHUNT OF 32 AN 43 BTW 32 / 43
+MOD OF 43 AN 64 BTW 43 modulo 64
+BIGGR OF 23 AN 53 BTW max(23, 53)
+SMALLR OF 53 AN 45 BTW min(53, 45)
+
+BTW binäre Notation:
+
+BOTH OF WIN AN WIN BTW und: WIN if x=WIN, y=WIN
+EITHER OF FAIL AN WIN BTW oder: FAIL if x=FAIL, y=FAIL
+WON OF WIN AN FAIL BTW exklusives oder: FAIL if x=y
+NOT FAIL BTW unäre Negation: WIN if x=FAIL
+ALL OF WIN AN WIN MKAY BTW beliebige Stelligkeit bei AND
+ANY OF WIN AN FAIL MKAY BTW beliebige Stelligkeit bei OR
+
+BTW Vergleiche:
+
+BOTH SAEM "CAT" AN "DOG" BTW WIN wenn x == y
+DIFFRINT 732 AN 184 BTW WIN wenn x != y
+BOTH SAEM 12 AN BIGGR OF 12 AN 4 BTW x >= y
+BOTH SAEM 43 AN SMALLR OF 43 AN 56 BTW x <= y
+DIFFRINT 64 AN SMALLR OF 64 AN 2 BTW x > y
+DIFFRINT 75 AN BIGGR OF 75 AN 643 BTW x < y
+
+OBTW
+ ==========================================================================
+ ============================= Flusskontrolle =============================
+ ==========================================================================
+TLDR
+
+BTW If/then Statement:
+I HAS A ANIMAL
+GIMMEH ANIMAL
+BOTH SAEM ANIMAL AN "CAT", O RLY?
+ YA RLY
+ VISIBLE "YOU HAV A CAT"
+ MEBBE BOTH SAEM ANIMAL AN "MAUS"
+ VISIBLE "NOM NOM NOM. I EATED IT."
+ NO WAI
+ VISIBLE "AHHH IS A WOOF WOOF"
+OIC
+
+BTW Case Statement:
+I HAS A COLOR
+GIMMEH COLOR
+COLOR, WTF?
+ OMG "R"
+ VISIBLE "RED FISH"
+ GTFO
+ OMG "Y"
+ VISIBLE "YELLOW FISH"
+ BTW Weil hier kein `GTFO` ist wird auch das nächste Statement überprüft
+ OMG "G"
+ OMG "B"
+ VISIBLE "FISH HAS A FLAVOR"
+ GTFO
+ OMGWTF
+ VISIBLE "FISH IS TRANSPARENT OHNO WAT"
+OIC
+
+BTW For Schleife:
+I HAS A TEMPERATURE
+GIMMEH TEMPERATURE
+TEMPERATURE IS NOW A NUMBR
+IM IN YR LOOP UPPIN YR ITERATOR TIL BOTH SAEM ITERATOR AN TEMPERATURE
+ VISIBLE ITERATOR
+IM OUTTA YR LOOP
+
+BTW While Schleife:
+IM IN YR LOOP NERFIN YR ITERATOR WILE DIFFRINT ITERATOR AN -10
+ VISIBLE ITERATOR
+IM OUTTA YR LOOP
+
+OBTW
+ =========================================================================
+ ================================ Strings ================================
+ =========================================================================
+TLDR
+
+BTW Zeilenumbrüche:
+VISIBLE "FIRST LINE :) SECOND LINE"
+
+BTW Tabulatoren:
+VISIBLE ":>SPACES ARE SUPERIOR"
+
+BTW Bell (macht beep):
+VISIBLE "NXT CUSTOMER PLS :o"
+
+BTW Anführungszeichen in Strings:
+VISIBLE "HE SAID :"I LIKE CAKE:""
+
+BTW Doppelpunkte in Strings :
+VISIBLE "WHERE I LIVE:: CYBERSPACE"
+
+OBTW
+ =========================================================================
+ =============================== Funktionen ==============================
+ =========================================================================
+TLDR
+
+BTW Definieren einer neuen Funktion:
+HOW IZ I SELECTMOVE YR MOVE BTW `MOVE` ist ein Argument
+ BOTH SAEM MOVE AN "ROCK", O RLY?
+ YA RLY
+ VISIBLE "YOU HAV A ROCK"
+ NO WAI
+ VISIBLE "OH NO IS A SNIP-SNIP"
+ OIC
+ GTFO BTW Gibt NOOB zurück
+IF U SAY SO
+
+BTW Eine Funktion deklarieren und einen Wert zurückgeben:
+HOW IZ I IZYELLOW
+ FOUND YR "YELLOW"
+IF U SAY SO
+
+BTW Eine Funktion aufrufen:
+I IZ IZYELLOW MKAY
+
+KTHXBYE
+```
+
+## Weiterführende Informationen:
+
+- [LCI compiler](https://github.com/justinmeza/lci)
+- [Official spec](https://github.com/justinmeza/lolcode-spec/blob/master/v1.2/lolcode-spec-v1.2.md)
diff --git a/de-de/asciidoc-de.html.markdown b/de-de/asciidoc-de.html.markdown
index 1a8cdd5a..e3f64a00 100644
--- a/de-de/asciidoc-de.html.markdown
+++ b/de-de/asciidoc-de.html.markdown
@@ -84,15 +84,11 @@ Abteilungstitel
===== Level 4 <h5>
-====== Level 5 <h6>
-
-======= Level 6 <h7>
-
```
Listen
-Um eine Aufzählung zu erstellen verwendest du Sternchen.
+Um eine Aufzählung zu erstellen, verwendest du Sternchen.
```
* foo
@@ -100,7 +96,7 @@ Um eine Aufzählung zu erstellen verwendest du Sternchen.
* baz
```
-Um eine nummerierte Liste zu erstellen verwendest du Punkte.
+Um eine nummerierte Liste zu erstellen, verwendest du Punkte.
```
. item 1
@@ -108,7 +104,7 @@ Um eine nummerierte Liste zu erstellen verwendest du Punkte.
. item 3
```
-Um Listen zu verschachteln musst du zusätzliche Sternchen und Punkte hinzufügen. Dies ist bis zu fünf Mal möglich.
+Um Listen zu verschachteln, musst du zusätzliche Sternchen beziehungsweise Punkte hinzufügen. Dies ist bis zu fünf Mal möglich.
```
* foo 1
diff --git a/de-de/bash-de.html.markdown b/de-de/bash-de.html.markdown
index 7928b136..3a76708a 100644
--- a/de-de/bash-de.html.markdown
+++ b/de-de/bash-de.html.markdown
@@ -157,7 +157,7 @@ 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)
+# (mit '-i' für "interactive" erfolgt für jede Datei 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:
@@ -180,7 +180,7 @@ esac
# 'for' Schleifen iterieren über die angegebene Zahl von Argumenten:
# Der Inhalt von $Variable wird dreimal ausgedruckt.
-for $Variable in {1..3}
+for Variable in {1..3}
do
echo "$Variable"
done
@@ -217,7 +217,7 @@ done
function foo ()
{
echo "Argumente funktionieren wie bei skripts: $@"
- echo Und: $1 $2..."
+ echo "Und: $1 $2..."
echo "Dies ist eine Funktion"
return 0
}
diff --git a/de-de/bc.html.markdown b/de-de/bc.html.markdown
new file mode 100644
index 00000000..49a2878d
--- /dev/null
+++ b/de-de/bc.html.markdown
@@ -0,0 +1,102 @@
+---
+language: bc
+contributors:
+ - ["caminsha", "https://github.com/caminsha"]
+filename: learnbc-de.bc
+lang: de-de
+---
+```c
+/* Das is ein mehr-
+zeiliger Kommentar */
+# Das ist ein (einzeiliger) Kommentar (in GNU bc).
+
+ /*1. Variablen und Kontrollstrukturen*/
+num = 45 /* Alle Variablen speichern nur Doubles und es ist
+ nicht möglich String-Konstanten direkt zu speichern */
+num = 45; /* Es kann nach jedem Statement ein optionales Semikolon
+ hinzugefügt werden */
+/* Blöcke werden mit den Operatoren {} (ähnlich wie in C) bezeichnet */
+while(num < 50) {
+ num += 1 /* äquivalent zu num=num+1.
+ a = a Op b ist äquivalent zu a Op= b*/
+}
+/* Ausserdem gibt es ++ (Inkrement) und -- (Dekrement) Operatoren */
+/* Es gibt 3 spezielle Variablen:
+scale: definiert die Anzahl Nachkommastellen
+ibase: definiert die Basis der Eingabe
+obase: definiert die Basis der Ausgabe*/
+/*Wenn-Bedingungen:*/
+hour = read() /*Eingabe einer Zahl*/
+
+if(hour < 12) { /*Operatoren sind genau wie in C*/
+ print "Guten Morgen\n" /*"print" Gibt Strings oder Variablen
+ mit einem Komma separiert aus.*/
+} else if(hour == 12) {
+ print "Hallo\n"
+ /* Escape-Sequenzen starten mite einem \ in einem String.
+ Um Escape-Sequenzen klarer zu machen, ist hier eine vereinfachte
+ Liste, welche in bc funktioneren.:
+ \b: Backspace
+ \c: carriage return
+ \n: Zeilenumbruch
+ \t: Tab
+ \\: Backslash*/
+} else {
+ /* Standardmässig sind Variablen global. */
+ thisIsGlobal = 5
+ /*Variablen können lokal gemacht werden. Benutze das Schlüsselwort "auto"
+ in einer Funktion.*/
+}
+
+/* Jede Variable hat als Voreinstellung den Wert 0. */
+num = blankVariable /*num wurde auf 0 gesetzt.*/
+
+/*Wie in C ist nur 0 falsch.*/
+if(!num) {print "false\n"}
+
+/*Im Gegensatz zu C hat bc den Ternäroperator ?: nicht. Zum Beispiel
+führt dieser Codeblok zu einem Fehler:
+a = (num) ? 1 : 0
+Jedoch kann dies simuliert werden:*/
+a = (num) && (1) || (0) /*&& ist das UND, || ist das ODER*/
+
+/*For-Schleifen*/
+num = 0
+for(i = 1; i <= 100; i++) {/*Gleich wie die For-Schleife in C*/
+ num += i
+}
+
+ /*2.Funktionen und Arrays*/
+define fac(n) { /*Definiere eine Funktion mit define*/
+ if(n == 1 || n == 0) {
+ return 1 /*Gebe einen Wert zurück*/
+ }
+ return n * fac(n - 1) /*Rekursion ist möglich*/
+}
+
+/*Closures und anonyme Funktionen sind nicht möglich */
+
+num = fac(4) /*24*/
+
+/*Dies ist ein Beispiel von lokalen Variabeln.*/
+define x(n) {
+ auto x
+ x = 1
+ return n + x
+}
+x(3) /*4*/
+print x /*Es stellt sich heraus, dass x ausserhalb der Funktion nicht
+ zugänglich ist.*/
+/*Arrays sind äquivalent zu C Arrays.*/
+for(i = 0; i <= 3; i++) {
+ a[i] = 1
+}
+/*Greife wie folgt darauf zu:*/
+print a[0], " ", a[1], " ", a[2], " ", a[3], "\n"
+quit /* Füge diese Codezeile hinzu, um sicherzustellen, dass
+das Programm beendet. Diese Codezeile ist optional.*/
+```
+Viel Spass mit diesem einfachen Rechner! (Oder dieser Programmiersprache, um exakt zu sein.)
+
+Das ganze Programm wurde in GNU bc geschrieben. Um es auszuführen, benutze ```bc learnbc.bc```.
+
diff --git a/de-de/c++-de.html.markdown b/de-de/c++-de.html.markdown
new file mode 100644
index 00000000..87e75ad6
--- /dev/null
+++ b/de-de/c++-de.html.markdown
@@ -0,0 +1,1158 @@
+---
+language: c++
+filename: learncpp-de.cpp
+contributors:
+ - ["Steven Basart", "http://github.com/xksteven"]
+ - ["Matt Kline", "https://github.com/mrkline"]
+ - ["Geoff Liu", "http://geoffliu.me"]
+ - ["Connor Waters", "http://github.com/connorwaters"]
+ - ["Ankush Goyal", "http://github.com/ankushg07"]
+ - ["Jatin Dhankhar", "https://github.com/jatindhankhar"]
+ - ["Maximilian Sonnenburg", "https://github.com/LamdaLamdaLamda"]
+ - ["caminsha", "https://github.com/caminsha"]
+lang: de-de
+---
+
+C++ ist eine Systemprogrammiersprache die,
+
+[laut dem Begründer Bjarne Stroustrup](http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2014/Keynote)
+entworfen wurde um,
+
+- "besseres C" zu sein
+- Datenabstraktion zu unterstützen
+- Objektorientierung zu unterstützen
+- generische Programmierung zu unterstützen
+
+Durch seine Syntax kann sie durchaus schwieriger und komplexer als neuere Sprachen sein.
+
+Sie ist weit verbreitet, weil sie in Maschinen-Code kompiliert, welcher direkt vom Prozessor ausgeführt
+werden kann und somit eine strikte Kontrolle über die Hardware bietet und gleichzeitig
+High-Level-Features wie generics, exceptions und Klassen enthält.
+
+Diese Kombination aus Geschwindigkeit und Funktionalität bildet C++ und ist eine der
+weitverbreitesten Programmiersprachen.
+
+```c++
+//////////////////
+// Vergleich zu C
+//////////////////
+
+// C ist fast eine Untermenge von C++ und teilt sich grundsätzlich die
+// Syntax für Variablen Deklarationen, primitiven Typen und Funktionen.
+
+// Wie in C ist der Programmeinsprungpunkt eine Funktion, welche "main" genannt wird und
+// einen Integer als Rückgabetyp besitzt.
+
+// Dieser Wert fungiert als Beendigungsstatus des Programms.
+// Siehe: https://de.wikipedia.org/wiki/Return_Code für weitere Informationen
+int main(int argc, char** argv)
+{
+ // Kommandozeilen Argumente werden genauso wie in C über argc und argv übergeben
+ // argc entspricht der Anzahl von Argumenten und argv ist ein Array von C-style
+ // strings (char*), welche die Argumente repräsentieren.
+ // Das erste Argument ist der Name des Programms, welches aufgerufen wird.
+ // Argc und argv können, wenn nicht benötigt, weg gelassen werden, indem
+ // die Funktionssignatur "int main()" verwendet wird.
+
+ // Ein Rückgabewert von 0 repräsentiert die erfolgreiche Ausführung.
+ return 0;
+}
+
+// C++ unterscheidet sich in einigen Punkten von C:
+
+// In C++ sind Zeichen-Literale char´s
+sizeof('c') == sizeof(char) == 1
+
+// In C sind Zeichen-Literale int´s
+sizeof('c') == sizeof(int)
+
+// C++ verwendet striktes prototyping
+void func(); // Funktion ohne Argumente
+
+// In C
+void func(); // Funktion mit beliebiger Anzahl von Argumenten
+
+// Verwende nullptr, anstatt von NULL!!!
+int* ip = nullptr;
+
+// C standard header sind in C++ verfügbar.
+// C header enden mit .h, während
+// C++ header das Präfix "c" besitzen und kein ".h" Suffix verwenden.
+
+// Die C++ Standard Version:
+#include <cstdio>
+
+// Die C Standard Version:
+#include <stdio.h>
+
+int main()
+{
+ printf("Hello, world!\n");
+ return 0;
+}
+
+///////////////////////
+// Funktionsüberladung
+///////////////////////
+
+// C++ unterstützt Funktionsüberladung
+// Jede Funktion kann unterschiedliche Parameter erhalten.
+void print(char const* myString)
+{
+ printf("String %s\n", myString);
+}
+
+void print(int myInt)
+{
+ printf("My int is %d", myInt);
+}
+
+int main()
+{
+ print("Hello"); // Wird aufgelöst zu "void print(const char*)"
+ print(15); // Wird aufgelöst zu "void print(int)"
+}
+
+/////////////////////////////
+// Standard Funktionsargumente
+/////////////////////////////
+
+// Argumente können per Standard für eine Funktion gesetzt werden,
+// wenn diese beim Aufruf nicht bereitgestellt werden.
+void doSomethingWithInts(int a = 1, int b = 4)
+{
+ // führe Anweisungen mit "int´s" aus.
+}
+
+int main()
+{
+ doSomethingWithInts(); // a = 1, b = 4
+ doSomethingWithInts(20); // a = 20, b = 4
+ doSomethingWithInts(20, 5); // a = 20, b = 5
+}
+
+// Standard-Argumente müssen am Ende der Liste der Argumente stehen.
+void invalidDeclaration(int a = 1, int b) // Fehler!
+{
+}
+
+
+/////////////
+// Namespaces (Namensräume)
+/////////////
+
+// Namespaces stellen einen getrennten Gültigkeitsbereich für Variablen,
+// Funktionen und andere Deklarationen zur Verfügung.
+// Namespaces können geschachtelt werden.
+namespace First
+{
+ namespace Nested
+ {
+ void foo()
+ {
+ printf("This is First::Nested::foo\n");
+ }
+ } // Ende des Namespace "Nested"
+} // Ende des Namespace "First"
+
+namespace Second
+{
+ void foo()
+ {
+ printf("This is Second::foo\n");
+ }
+}
+
+void foo()
+{
+ printf("This is global foo\n");
+}
+
+int main()
+{
+ // Fügt alle Symbole aus dem namespace Second in den aktuellen Gültigkeitsbereich (scope).
+ // "foo()" wird nun nicht länger funktionieren, da es nun doppeldeutig ist, ob foo aus
+ // dem namespace foo oder darüberliegenden aufgerufen wird.
+ using namespace Second;
+
+ Second::foo(); // Gibt "This is Second::foo" aus.
+ First::Nested::foo(); // Gibt "This is First::Nested::foo" aus.
+ ::foo(); // Gibt "This is global foo" aus.
+}
+
+///////////////
+// Eingabe/Ausgabe
+///////////////
+
+// C++ verwendet für die Eingabe und Ausgabe streams.
+// cin, cout und cerr repräsentieren stdin, stdout und stderr.
+// << ist der Einfügeoperator und >> ist der Extraktionsoperator.
+
+#include <iostream> // Include für Eingabe/Ausgabe (I/O) streams
+
+using namespace std; // Streams befinden sich im std namespace (standard library)
+
+int main()
+{
+ int myInt;
+
+ // Ausgabe auf stdout (oder Terminal/Bildschirm)
+ cout << "Enter your favorite number:\n";
+
+ // Empfängt Eingabe
+ cin >> myInt;
+
+ // cout kann ebenfalls formatiert werden
+ cout << "Your favorite number is " << myInt << "\n";
+ // Gibt "Your favorite number is <myInt>" aus
+
+ cerr << "Used for error messages";
+}
+
+//////////
+// Zeichenketten (Strings)
+//////////
+
+// Strings in C++ sind Objekte und haben diverse member-functions
+#include <string>
+
+using namespace std; // Strings sind ebenfalls im namespace std (Standard Bibliothek)
+
+string myString = "Hello";
+string myOtherString = " World";
+
+// + wird für das Anhängen von strings verwendet.
+cout << myString + myOtherString; // "Hello World"
+
+cout << myString + " You"; // "Hello You"
+
+// C++ strings sind mutable.
+myString.append(" Dog");
+cout << myString; // "Hello Dog"
+
+
+/////////////
+// Referenzen
+/////////////
+
+// Zusätzlich zu Pointern, wie jene in C.
+// C++ besitzt _Referenzen_.
+// Diese sind Pointer-Typen, welche nicht erneut zugewiesen werden können
+// und nicht Null sein können.
+// Sie besitzen den selben Syntax wie Variablen.
+// Für die Dereferenzierung ist kein * notwendig und
+// & (die Adresse) wird nicht für die Zuweisung verwendet.
+
+using namespace std;
+
+string foo = "I am foo";
+string bar = "I am bar";
+
+
+string& fooRef = foo; // Erzeugt eine Referenz auf foo.
+fooRef += ". Hi!"; // Verändert foo durch die Referenz
+cout << fooRef; // Gibt "I am foo. Hi!" aus.
+
+
+// Weist "fooRef" nicht erneut zu. Dies ist dasselbe, wie "foo = bar" und
+// foo == "I am bar"
+// nach dieser Zeile
+cout << &fooRef << endl; // Gibt die Adresse von foo aus
+fooRef = bar;
+cout << &fooRef << endl; // Gibt ebenfalls die Adresse von foo aus
+cout << fooRef; // Gibt "I am bar" aus
+
+// Die Adresse von fooRef verbleibt die selbe, sie verweist immer noch auf foo
+
+const string& barRef = bar; // Erzeugt konstante Referenz auf bar.
+// Wie in C, können konstante Werte ( und Pointer bzw. Referenzen) nicht verändert werden.
+
+barRef += ". Hi!"; // Fehler: konstante Referenzen können nicht verändert werden.
+
+// Hinweis: bevor wir genauer Referenzen besprechen, schauen wir uns zuerst ein Konzept an,
+// welches als "temporäres Objekt" bezeichnet wird. Gehen wir von folgenden Code aus:
+string tempObjectFun() { ... }
+string retVal = tempObjectFun();
+
+// Was passiert nun in der zweiten Zeile:
+// - ein String Objekt wird von "tempObjectFun" zurückgegeben
+// - ein neuer String wird mit dem zurückgegebenen Objekt als Argument für den Konstruktor erzeugt.
+// - das zurückgegebene Objekt wird zerstört
+// Das zurückgegbene Objekt wird temporäres Objekt genannt. Temporäre Objekte werden erzeugt
+// wann immer eine Funktion ein Objekt zurückgibt. Zerstört werden diese am Ende der Auswertung des Ausdrucks
+// (dies schreibt der Standard vor, aber Compiler sind berechtigt dieses Verhalten zu ändern. Siehe "return value optimization"
+// für Details). Wie in diesem Code:
+foo(bar(tempObjectFun()))
+
+// Nehmen wir an, foo und bar existieren. Das Objekt wird von "tempObjectFun" zurückgegeben,
+// wird an bar übergeben und ist zerstört bevor foo aufgerufen wird.
+
+// Zurück zu Referenzen. Die Annahme, dass die "am Ende des Ausdrucks" Regel gültig ist,
+// wenn das temporäre Objekt an eine konstante Referenz gebunden ist, ist der Fall, wenn die Lebensdauer
+// auf den aktuellen Gültigkeitsbereich erweitert wird.
+
+void constReferenceTempObjectFun() {
+ // constRef erhält das temporäre Objekt und ist gültig bis ans Ende der Funktion
+ const string& constRef = tempObjectFun();
+ ...
+}
+
+// Eine andere Art von Referenzen wurde in C++11 eingeführt und ist speziell für
+// temporäre Objekte. Es ist nicht möglich Variablen des Typs zu besitzen, aber
+// Vorrechte bei der Auflösung zu besitzen.
+
+void someFun(string& s) { ... } // Reguläre Referenz
+void someFun(string&& s) { ... } // Referenz auf ein temporäres Objekt
+
+string foo;
+someFun(foo); // Ruft die Funktion mit der regulären Referenz auf
+someFun(tempObjectFun()); // Ruft die Funktion mit der temporären Referenz auf
+
+// Zum Beispiel existieren diese zwei Varianten von Konstruktoren für
+// std::basic_string:
+basic_string(const basic_string& other);
+basic_string(basic_string&& other);
+
+// Nehmen wir an, wir erzeugen einen neuen String eines temporären Objekts (welches später
+// zerstört wird), hierbei existiert ein effizienterer Konstruktor. Dieses Konzept wird
+// als "move semantics" bezeichnet (bewegen eines Objekts in ein anderes in C++).
+
+/////////////////////
+// Enumerations (Aufzählungstypen)
+/////////////////////
+
+// Enums sind eine einfachere Art und Weise einen Wert einer Konstante zu zuweisen.
+// Häufig wird dies verwendet, um den Code lesbarer zu gestalten bzw. zu visualisieren.
+enum ECarTypes
+{
+ Sedan,
+ Hatchback,
+ SUV,
+ Wagon
+};
+
+ECarTypes GetPreferredCarType()
+{
+ return ECarTypes::Hatchback;
+}
+
+// Mit C++11 existiert eine einfache Möglichkeit einem Typ dem Enum zuzuweisen. Dies
+// kann durchaus sinnvoll bei der Serialisierung von Daten sein, oder bei der Konvertierung
+// zwischen Typen bzw. Konstanten.
+enum ECarTypes : uint8_t
+{
+ Sedan, // 0
+ Hatchback, // 1
+ SUV = 254, // 254
+ Hybrid // 255
+};
+
+void WriteByteToFile(uint8_t InputValue)
+{
+ // Serialisierung von "InputValue" in eine Datei
+}
+
+void WritePreferredCarTypeToFile(ECarTypes InputCarType)
+{
+ // Das enum wird implizit zu einem "uint8_t" konvertiert. Bedingt dadurch, dass
+ // es sich um ein "enum" handelt.
+ WriteByteToFile(InputCarType);
+}
+
+// Nicht immer ist es gewünscht, dass enum´s zu einem Integer oder zu einem anderen
+// enum umgewandelt werden. Daher ist es möglich eine enum-Klasse zu erzeugen, welche
+// nicht implizit umgewandelt wird.
+enum class ECarTypes : uint8_t
+{
+ Sedan, // 0
+ Hatchback, // 1
+ SUV = 254, // 254
+ Hybrid // 255
+};
+
+void WriteByteToFile(uint8_t InputValue)
+{
+ // Serialisierung von InputValue in eine Datei
+}
+
+void WritePreferredCarTypeToFile(ECarTypes InputCarType)
+{
+ // Wird nicht kompilieren, da "ECarTypes" ein "uint8_t" ist, da das enum
+ // als "enum class" deklariert wurde!
+ WriteByteToFile(InputCarType);
+}
+
+//////////////////////////////////////////
+// Klassen und objekorientierte Programmierung
+//////////////////////////////////////////
+
+// Erstes Beispiel einer Klasse
+#include <iostream>
+
+// Deklaration einer Klasse.
+// Klassen werden üblicherweise im header (.h oder .hpp) deklariert.
+class Dog
+{
+ // Member Variablen und Funktionen sind private per default (standard).
+ std::string name;
+ int weight;
+
+// Alle nachfolgenden member sind "public" bis
+// "private:" oder "protected:" auftritt.
+public:
+
+ // Standard Konstruktor
+ Dog();
+
+ // Member-Funktionsdeklaration (Implementierung folgt).
+ // Bemerkung: std::string statt der Verwendung von namespace std;
+ // "using namespace" sollte niemals in einem header verwendet werden.
+ void setName(const std::string& dogsName);
+
+ void setWeight(int dogsWeight);
+
+ // Funktionen, die Objekte nicht ändern, sollten mit const deklariert werden.
+ // Funktionen müssen explizit als "virtual" deklariert werden, um in einer
+ // abgeleiteten Klassen überschrieben zu werden.
+ // Aus performance Gründen sind Funktionen nicht per default virtual.
+ virtual void print() const;
+
+ // Funktionen können ebenfalls im class body definiert werden.
+ // Derart definierte Funktionen sind automatisch "inline".
+ void bark() const { std::cout << name << " barks!\n"; }
+
+ // Neben Konstruktoren, bietet C++ Destruktoren.
+ // Diese werden aufgerufen, wenn ein Objekt freigegeben wird oder
+ // seinen Wertebereich verlässt.
+ // Dies ermöglicht mächtige Paradigmen, wie auch RAII.
+ // Destruktoren sollten virtual sein, wenn eine Klasse von ihr
+ // abgeleitet wird. Ist dieser nicht virtual, dann wird der
+ // Destruktor der abgeleiteten Klasse nicht aufgerufen, insofern
+ // das Objekt durch eine Referenz/Pointer der Basisklasse entfernt wird.
+ virtual ~Dog();
+
+}; // Ein Semikolon schließt die Definition der Klasse ab.
+
+// Klassen-Member-Funktionen sind üblicherweise in der .cpp Datei implementiert.
+Dog::Dog()
+{
+ std::cout << "A dog has been constructed\n";
+}
+
+// Objekte sollten als Referenz übergeben werden und wenn diese nicht
+// verändert werden sollen, sollte das Objekt als const Referenz übergeben werden.
+void Dog::setName(const std::string& dogsName)
+{
+ name = dogsName;
+}
+
+void Dog::setWeight(int dogsWeight)
+{
+ weight = dogsWeight;
+}
+
+// "Virtual" wird nur bei der Deklaration benötigt und nicht bei der Definition.
+void Dog::print() const
+{
+ std::cout << "Dog is " << name << " and weighs " << weight << "kg\n";
+}
+
+Dog::~Dog()
+{
+ std::cout << "Goodbye " << name << "\n";
+}
+
+int main()
+{
+ Dog myDog; // Ausgabe: "A dog has been constructed"
+ myDog.setName("Barkley");
+ myDog.setWeight(10);
+ myDog.print(); // Ausgabe: "Dog is Barkley and weighs 10 kg"
+ return 0;
+} // Ausgabe: "Goodbye Barkley"
+
+// Diese Klasse erbt alles was public bzw. protected ist von der Dog-Klasse
+// und darüber hinaus auch private Methoden/Attribute, jedoch kann auf diese
+// nicht direkt zugegriffen werden. Lediglich über public/procted getter/setter.
+class OwnedDog : public Dog {
+
+public:
+ void setOwner(const std::string& dogsOwner);
+
+ // Überschreibt das Verhalten der "print" Funktion für alle "OwnedDogs".
+ // Siehe: http://en.wikipedia.org/wiki/Polymorphism_(computer_science)#Subtyping
+ // für eine grundlegende Einführung in "Subtype Polymorphismus".
+ // Das "override" Schlüsselwort ist optional, aber stellt sicher, dass die
+ // Methode der Basisklasse tatsächlich überschrieben wurde.
+ void print() const override;
+
+private:
+ std::string owner;
+};
+
+// Die zugehörige .cpp Datei
+void OwnedDog::setOwner(const std::string& dogsOwner)
+{
+ owner = dogsOwner;
+}
+
+void OwnedDog::print() const
+{
+ Dog::print(); // Ruft die "print" Funktion der Basisklasse auf.
+ std::cout << "Dog is owned by " << owner << "\n";
+ // Ausgaben: "Dog is <name> and weights <weight>"
+ // "Dog is owned by <owner>"
+}
+
+//////////////////////////////////////////
+// Initialisierung und Operatorüberladung
+//////////////////////////////////////////
+
+// In C++ können Operatoren wie: +, -, *, / etc. überladen werden.
+// Dies wird umgesetzt, indem eine entsprechende Funktion definiert wird,
+// welche immer dann aufgerufen wird, sobald der Operator verwendet wird.
+#include <iostream>
+using namespace std;
+
+class Point
+{
+public:
+ // Member Variablen können mit einem default Wert initialisiert werden.
+ double x = 0;
+ double y = 0;
+
+ // Definition des Standard Konstruktor, welcher nichts tut
+ // außer den Punkt auf den default Wert (0,0) zu setzen.
+ Point() { };
+
+ // Die nachfolgende Syntax ist bekannt als "initialization list"
+ // und ist eine gängige Art Klassen-Member zu initialisieren.
+ Point (double a, double b) :
+ x(a),
+ y(b)
+ { /* Außschließliche Initialisierung der Werte */ }
+
+ // Überladung des "+" Operator.
+ Point operator+(const Point& rhs) const;
+
+ // Überladung des "+=" Operator
+ Point& operator+=(const Point& rhs);
+
+ // Sinnhaft wäre es an dieser Stelle den "-" und "-=" Operator
+ // ebenfalls zu überladen.
+};
+
+Point Point::operator+(const Point& rhs) const
+{
+ // Erzeugung eines neuen Punkts, welcher die Summe aus sich
+ // selbst und "rhs" bildet
+ return Point(x + rhs.x, y + rhs.y);
+}
+
+Point& Point::operator+=(const Point& rhs)
+{
+ x += rhs.x;
+ y += rhs.y;
+ return *this;
+}
+
+int main ()
+{
+ Point up (0,1);
+ Point right (1,0);
+
+ // Ruft den + Operator mit den entsprechenden Parametern auf.
+ Point result = up + right;
+ // Ausgabe: "Result is upright (1,1)"
+ cout << "Result is upright (" << result.x << ',' << result.y << ")\n";
+ return 0;
+}
+
+/////////////////////
+// Templates
+/////////////////////
+
+// Templates in C++ werden in erster Linie dafür verwendet generisch zu programmieren.
+// Sie unterstützen explizite und partielle Spezialisierung und darüber hinaus können
+// sie für funktionale Klassen verwendet werden.
+// Tatsächlich bilden Templates die Turing-Vollständigkeit
+// (universelle Programmierbarkeit) ab.
+
+
+// Zu Beginn ein einführendes Beispiel der generischen Programmierung.
+// Die Definition einer Klasse bzw. Funktion, welche mit dem Typ T parametriert wird.
+template<class T>
+class Box
+{
+public:
+ // T repräsentiert an dieser Stelle einen beliebigen Typen.
+ void insert(const T&) { ... }
+};
+
+// Während der Kompilierung generiert der Compiler Kopien für jedes Template, wobei
+// hierbei die Parameter substituiert werden. Somit muss bei jedem Aufruf die gesamte
+// Definition der Klasse zur Verfügung stehen. Aus diesem Grund wird ein Template
+// komplett im header definiert.
+
+// Erzeugung einer Template-Klasse auf dem Stack:
+Box<int> intBox;
+
+// eine der zu erwartenden Verwendungen:
+intBox.insert(123);
+
+// Verschachtelungen von Templates sind möglich.
+Box<Box<int> > boxOfBox;
+boxOfBox.insert(intBox);
+
+// Bis C++11 war es erforderlich ein Leerzeichen zwischen '>' einzufügen,
+// andernfalls wurde es als '>>' geparsed (right shift).
+
+// Manchmal ist folgende Notation anzutreffen:
+// template<typename T>
+// Das 'class' Schlüsselwort und das 'typename' Schlüsselwort
+// sind fast identisch hinsichtlich der Funktionalität. Weitere
+// Informationen auf: http://en.wikipedia.org/wiki/Typename
+
+// Eine Template-Funktion:
+template<class T>
+void barkThreeTimes(const T& input)
+{
+ input.bark();
+ input.bark();
+ input.bark();
+}
+
+// Hierbei ist zu beachten, dass an dieser Stelle nichts über den Typen des Parameters
+// definiert wurde. Der Compiler wird bei jedem Aufruf bzw. jeder Erzeugung den Typen
+// prüfen. Somit funktioniert die zuvor definierte Funktion für jeden Typ 'T', die die
+// const Methode 'bark' implementiert hat.
+
+Dog fluffy;
+fluffy.setName("Fluffy")
+barkThreeTimes(fluffy); // Gibt "Fluffy barks" dreimal aus.
+
+// Template Parameter müssen keine Klassen sein.
+template<int Y>
+void printMessage()
+{
+ cout << "Learn C++ in " << Y << " minutes!" << endl;
+}
+
+// Des Weiteren können Templates aus Effizienzgründen genauer spezifiziert werden.
+// Selbstverständlich sind reale Probleme, welche genauer spezifiziert werden, nicht
+// derart trivial. Auch wenn alle Parameter explizit definiert wurden, muss die
+// Funktion oder Klasse als Template deklariert werden.
+template<>
+void printMessage<10>()
+{
+ cout << "Learn C++ faster in only 10 minutes!" << endl;
+}
+
+printMessage<20>(); // Gibt "Learn C++ in 20 minutes!" aus.
+printMessage<10>(); // Gibt "Learn C++ faster in only 10 minutes!" aus.
+
+
+/////////////////////
+// Ausnahme Behandlungen (Exception-Handling)
+/////////////////////
+
+// Die Standard Bibliothek bietet einige exceptions.
+// Siehe: http://en.cppreference.com/w/cpp/error/exception.
+// Grundsätzlich können alle Typen als exception geworfen werden.
+#include <exception>
+#include <stdexcept>
+
+// Alle exceptions, die in dem "try" Block geworfen werden, können mittels
+// "catch" abgefangen werden.
+try
+{
+ // exceptions sollten nicht auf dem heap mithilfe
+ // von "new" allokiert werden.
+ throw std::runtime_error("A problem occurred");
+}
+
+// Exceptions sollten als const Referenz abgefangen werden
+// insofern diese Objekte sind.
+catch (const std::exception& ex)
+{
+ std::cout << ex.what();
+}
+
+// Abfangen aller Exceptions, welche zuvor nicht abgefangen wurden.
+catch (...)
+{
+ std::cout << "Unknown exception caught";
+ throw; // Erneutes werfen der exception
+}
+
+///////
+// RAII
+///////
+
+// RAII steht für "Resource Acquisition Is Initialization".
+// Oft wird dies als eines der wichtigsten Paradigmen in C++ betrachtet.
+// RAII beschreibt das Konzept, dass der Konstruktor für ein Objekt
+// die Ressourcen akquiriert und der Destruktor diese freigibt.
+
+// Zum Verständnis, warum dies sinnvoll ist, nachfolgend
+// ein einführendes Beispiel:
+void doSomethingWithAFile(const char* filename)
+{
+ // Wir nehmen an, dass nichts schiefgehen wird.
+ FILE* fh = fopen(filename, "r"); // Öffnen der Datei im read-mode.
+
+ doSomethingWithTheFile(fh);
+ doSomethingElseWithIt(fh);
+
+ fclose(fh); // Schließen des file-handle.
+}
+
+// Unglücklicherweise ist die Fehlerbehandlung äußerst kompliziert.
+// Sollte fopen fehlschlagen und "doSomethingWithTheFile" bzw.
+// "doSomethingElseWithIt", geben diese einen Fehlercode zurück.
+// (Exceptions sind eine bevorzugte Möglichkeit Fehler abzufangen
+// , allerdings bei einigen Programmierern, besonders solchen die einen C
+// background besitzen, ein unbeliebtes Mittel zur Fehlerbehandlung).
+// Nun müssen wir jeden Aufruf auf mögliche auftretende Fehler überprüfen.
+bool doSomethingWithAFile(const char* filename)
+{
+ FILE* fh = fopen(filename, "r"); // Öffnet die Datei im read-mode
+ if (fh == nullptr) // Der Pointer ist bei einem Fehler NULL .
+ return false; // Benachrichtigt den Aufrufer über den Fehler.
+
+ // Wir nehmen an, dass jede Funktion false zurückgibt, in einem Fehlerfall
+ if (!doSomethingWithTheFile(fh))
+ {
+ fclose(fh); // File handle schließen.
+ return false; // Fehler "melden".
+ }
+
+ if (!doSomethingElseWithIt(fh))
+ {
+ fclose(fh); // File handle schließen.
+ return false; // Fehler "melden".
+ }
+
+ fclose(fh); // File handle schließen.
+ return true; // Erfolg "melden".
+}
+
+// C-Programmierer handhaben dies häufig durch goto-Anweisungen:
+bool doSomethingWithAFile(const char* filename)
+{
+ FILE* fh = fopen(filename, "r");
+ if (fh == nullptr)
+ return false;
+
+ if (!doSomethingWithTheFile(fh))
+ goto failure;
+
+ if (!doSomethingElseWithIt(fh))
+ goto failure;
+
+ fclose(fh); // File handle schließen.
+ return true; // Erfolg "melden".
+
+failure:
+ fclose(fh);
+ return false; // Fehler "melden".
+}
+
+// Insofern Funktionen Fehler durch exceptions indizieren,
+// ist dies "sauberer", aber immer noch suboptimal.
+void doSomethingWithAFile(const char* filename)
+{
+ FILE* fh = fopen(filename, "r"); // Öffnet die Datei im read-mode
+ if (fh == nullptr)
+ throw std::runtime_error("Could not open the file.");
+
+ try
+ {
+ doSomethingWithTheFile(fh);
+ doSomethingElseWithIt(fh);
+ }
+ catch (...)
+ {
+ // Im Fehlerfall sollte sichergestellt sein, dass die
+ // Datei geschlossen wird.
+ fclose(fh);
+ throw; // Erneutes werfen der exception
+ }
+
+ fclose(fh); // Schließen der Datei
+}
+
+// Folgendes ist mit der C++ file stream Klasse (fstream) zu vergleichen.
+// fstream verwendet den Destruktor, um die Datei zu schließen.
+// Der obige Destruktor wird automatisch aufgerufen, sobald das Objekt
+// den Gültigkeitsbereich verlässt.
+void doSomethingWithAFile(const std::string& filename)
+{
+ // ifstream entspricht der Kurzform von "input file stream".
+ std::ifstream fh(filename); // Öffnen der Datei
+
+ doSomethingWithTheFile(fh);
+ doSomethingElseWithIt(fh);
+
+} // Die Datei wird automatisch vom Destruktor geschlossen.
+
+// Diese Vorgehensweise bietet massive Vorteile:
+// 1. Egal was passiert, die Ressource (das Datei-Handle) wird aufgelöst,
+// insofern der Destruktor korrekt beschrieben wurde. Es ist möglich
+// zu vergessen das Datei-Handle zu schließen, was zu einem "leak" der
+// entsprechenden Ressource führt.
+// 2. Der Code selbst ist wesentlich "sauberer".
+// Der Destruktor wird das Datei-Handle im Hintergrund schließen und der
+// Programmierer muss sich darum keinerlei Sorgen machen.
+// 3. Der Code ist "exception sicher".
+// Egal wo die exception geworfen wird, das Aufräumen wird definitiv vollzogen.
+
+// Der gesamte idiomatische C++ Code verwendet RAII für alle Ressourcen.
+// Weitere Beispiele:
+// - Speicher verwenden "unique_ptr" und "shared_ptr".
+// - Container - verkettete Listen (linked list), vector (selbst organisierende
+// Arrays), hash maps, etc., entfernen deren Inhalt, wenn diese außerhalb des
+// Gültigkeitsbereichs laufen.
+// - Mutex´s verwenden lock_guard und unique_lock.
+
+/////////////////////
+// Container
+/////////////////////
+
+// Die Container der Standard template Bibliothek beinhaltet einige vordefinierte Templates.
+// Diese verwalten die Speicherbereiche für die eigenen Elemente und stellen Member-Funktionen
+// für den Zugriff und die Manipulation bereit.
+
+// Beispielhafte Container:
+
+// Vector (dynamisches array)
+// Erlaubt das Definieren von Arrays oder Listen zur Laufzeit
+#include <vector>
+string val;
+vector<string> my_vector; // Initialisierung des Vectors.
+cin >> val;
+my_vector.push_back(val); // Fügt den Wert "val" zum Vektor "my_vector" hinzu.
+my_vector.push_back(val); // Fügt den Wert "val" zum Vektor "my_vector" hinzu (nun zwei Elemente).
+
+// Für die Iteration über Vektoren stehen zwei Methodiken zu Verfügung:
+// Entweder die klassische Iteration über den Index:
+for (int i = 0; i < my_vector.size(); i++)
+{
+ cout << my_vector[i] << endl; // Zugriff auf die Elemente des Vektors über den [] Operator
+}
+
+// Oder die Verwendung von Iteratoren:
+vector<string>::iterator it; // Initialisierng des Iterators.
+for (it = my_vector.begin(); it != my_vector.end(); ++it)
+{
+ cout << *it << endl;
+}
+
+// Set (Mengen)
+// Sets sind Container, welche einzigartige Elemente beinhalten die einer
+// spezifischen Ordnung folgen.
+
+#include<set>
+set<int> ST; // Initialisierung des Sets mit einem Integer Datentyp.
+ST.insert(30); // Einfügen des Werts 30 in das Set ST
+ST.insert(10); // Einfügen des Werts 10 in das Set ST
+ST.insert(20); // Einfügen des Werts 20 in das Set ST
+ST.insert(30); // Einfügen des Werts 30 in das Set ST
+// Folgende Elemente befinden sich nun in dem Set:
+// 10 20 30
+
+// Entfernen eines Elements:
+ST.erase(20);
+
+// Set ST: 10 30
+// Für das iterieren verwenden wir Iteratoren:
+set<int>::iterator it;
+
+for(it=ST.begin();it<ST.end();it++)
+{
+ cout << *it << endl;
+}
+
+// Ausgabe:
+// 10
+// 30
+
+// Zum leeren des gesamten Containers wird die Methode
+// Container._name.clear() verwendet.
+ST.clear();
+cout << ST.size(); // Ausgabe der Set-Größe
+
+// Ausgabe: 0
+
+// Bemerkung: für mehrdeutige Elemente werden multisets verwendet.
+// Für hash-Sets sollten unordered_set´s verwendet werden, da diese
+// wesentlich effizienter sind, allerdings keiner Ordnung folgen.
+// Verfügbar sind diese Features ab C++11.
+
+// Map
+// Maps speichern Elemente, welche einer Kombination aus "Key"
+// und "Value" folgen.
+
+#include<map>
+map<char, int> mymap; // Initialisierung der Map: char -> Key, int -> Value.
+
+mymap.insert(pair<char,int>('A',1)); // Einfügen des Werts "1" für den Key "A".
+
+mymap.insert(pair<char,int>('Z',26)); // Einfügen des Werts "26" für den Key "Z".
+
+// Das Iterieren über Maps:
+map<char,int>::iterator it;
+for (it=mymap.begin(); it!=mymap.end(); ++it)
+ std::cout << it->first << "->" << it->second << '\n';
+
+// Ausgabe:
+// A->1
+// Z->26
+
+// Für das Finden des dazugehörigen Value des Keys.
+it = mymap.find('Z');
+cout << it->second;
+
+// Ausabe: 26
+
+// Bemerkung: für "hash maps" sollten die "unordered_map´s" verwendet werden. Diese
+// sind effizienter und benötigen keine Reihenfolge. "unordered_maps" sind ab
+// C++11 verfügbar.
+
+// Container für nicht-primitive Datentypen benötigen Vergleichsfunktionen im Objekt selbst,
+// oder als Funktionspointer. Primitive Datentypen besitzen default-Vergleichsfunktionen.
+// Allerdings können diese überschrieben werden.
+class Foo
+{
+public:
+ int j;
+ Foo(int a) : j(a) {}
+};
+
+struct compareFunction
+{
+ bool operator()(const Foo& a, const Foo& b) const
+ {
+ return a.j < b.j;
+ }
+};
+
+// Folgender Code ist nicht valide, könnte aber von einigen Compilern
+// als valide angesehen werden:
+// std::map<Foo, int> fooMap;
+std::map<Foo, int, compareFunction> fooMap;
+fooMap[Foo(1)] = 1;
+fooMap.find(Foo(1)); // Wahr
+
+
+///////////////////////////////////////
+// Lambda Ausdrücke (C++11 und höher)
+///////////////////////////////////////
+
+// Lambdas sind eine gängige Methodik, um anonyme Funktionen an dem
+// Ort der Verwendung zu definieren. Darüber hinaus auch bei der
+// Verwendung von Funktionen als Argument einer Funktion.
+
+// Nehmen wir an, es soll ein Vektor von "pairs" (Paaren) mithilfe
+// des zweiten Werts des "pairs" sortiert werden.
+
+vector<pair<int, int> > tester;
+tester.push_back(make_pair(3, 6));
+tester.push_back(make_pair(1, 9));
+tester.push_back(make_pair(5, 0));
+
+// Übergabe des Lambda-Ausdrucks als drittes Argument für die nachfolgende Sortierfunktion.
+sort(tester.begin(), tester.end(), [](const pair<int, int>& lhs, const pair<int, int>& rhs)
+{
+ return lhs.second < rhs.second;
+});
+
+// Beachte die Syntax von Lambda-Ausdrücken.
+// Die [] im Lambda Ausdruck werden für die Variablen verwendet.
+// Diese so genannte "capture list" definiert, was außerhalb des Lambdas,
+// innerhalb der Funktion verfügbar sein soll und in welcher Form.
+// Dies kann folgendes sein:
+// 1. ein Wert [x]
+// 2. eine Referenz [&x]
+// 3. eine beliebige Variable, welche sich im Gültigkeitsbereich durch
+// die Referenz [&] befindet.
+// 4. wie bei 3. aber mithilfe des Werts [=]
+// Beispiel:
+
+vector<int> dog_ids;
+
+for(int i = 0; i < 3; i++)
+{
+ dog_ids.push_back(i);
+}
+
+int weight[3] = {30, 50, 10};
+
+// Nehmen wir an wir möchten die "dog_ids" gemäß des Gewichts des Hundes sortieren.
+// So sollten sich die "dog_ids" wie folgt verhalten: [2, 0, 1]
+
+// Hier werden Lambdas praktisch:
+sort(dog_ids.begin(), dog_ids.end(), [&weight](const int &lhs, const int &rhs)
+{
+ return weight[lhs] < weight[rhs];
+});
+
+
+// Weiterführender Link über Lambda-Ausdrücke:
+// http://stackoverflow.com/questions/7627098/what-is-a-lambda-expression-in-c11
+
+///////////////////////////////
+// Range For (C++11 und höher)
+///////////////////////////////
+
+// Range-For Schleifen können verwendet werden, um über Container zu iterieren.
+int arr[] = {1, 10, 3};
+
+for(int elem: arr)
+{
+ cout << elem << endl;
+}
+
+// Insofern "auto" verwendet wird, muss der Typ nicht weiter beachtet werden.
+for(auto elem: arr)
+{
+ // Anweisungen ...
+}
+
+/////////////////////
+// Weiteres:
+/////////////////////
+
+// Einige Aspekte von C++ sind für Neueinsteiger häufig überraschend (aber auch für
+// C++ Veteranen).
+// Der nachfolgende Abschnitt ist leider nicht vollständig:
+// C++ ist eine der Sprachen, bei der es ein Leichtes ist, sich selbst ins Bein zu schießen.
+
+// Private-Methoden können überschrieben werden
+class Foo
+{
+ virtual void bar();
+};
+
+class FooSub : public Foo
+{
+ virtual void bar(); // Überschreibt Foo::bar!
+};
+
+// 0 == false == NULL
+bool* pt = new bool;
+*pt = 0; // Setzt den Wert des Pointers 'pt' auf false.
+pt = 0; // Setzt 'pt' auf den "null-pointer". Keine Compiler-Warnung.
+
+// nullptr sollte dieses Problem nicht lösen:
+int* pt2 = new int;
+*pt2 = nullptr; // Kompiliert nicht.
+pt2 = nullptr; // Setzt pt2 auf null.
+
+// Eine Ausnahme bilden bool´s.
+// Dies erlaubt es "null-pointer" zu testen: if(!ptr)
+// Die Konsequenz ist jedoch, dass dem nullptr ein bool zugewiesen werden kann.
+*pt = nullptr; // Kompiliert auch, wenn '*pt' ein bool ist!
+
+// '=' != '=' != '='!
+// Ruft Foo::Foo(const Foo&) auf, oder den Kopierkonstruktor
+Foo f2;
+Foo f1 = f2;
+
+// Ruft Foo::Foo(const Foo&) auf, aber kopiert lediglich den "Foo" Teil von
+// "fooSub". Alle zusätzlichen Member werden verworfen. Diese eigenartige Verhalten
+// wird auch "object slicing" genannt.
+FooSub fooSub;
+Foo f1 = fooSub;
+
+// Ruft Foo::operator=(Foo&) oder eine andere Variante auf.
+Foo f1;
+f1 = f2;
+
+///////////////////////////////////////
+// Tuple (C++11 und höher)
+///////////////////////////////////////
+
+#include<tuple>
+
+// Konzeptionell sind Tupel alten Datenstrukturen sehr ähnlich, allerdings haben diese keine
+// bezeichneten Daten-Member, sondern werden durch die Reihenfolge angesprochen.
+
+// Erstellen des Tupels und das Einfügen eines Werts.
+auto first = make_tuple(10, 'A');
+const int maxN = 1e9;
+const int maxL = 15;
+auto second = make_tuple(maxN, maxL);
+
+// Ausgabe der Elemente des "first" Tuple.
+cout << get<0>(first) << " " << get<1>(first) << "\n"; // Ausgabe : 10 A
+
+// Ausgabe der Elemente des "second" Tuple.
+cout << get<0>(second) << " " << get<1>(second) << "\n"; // Ausgabe: 1000000000 15
+
+int first_int;
+char first_char;
+tie(first_int, first_char) = first;
+cout << first_int << " " << first_char << "\n"; // Ausgabe : 10 A
+
+// Tuple können auch wie folgt erzeugt werden:
+
+tuple<int, char, double> third(11, 'A', 3.14141);
+// tuple_size gibt die Anzahl der Elemente in einem Tuple zurück.
+// Als "constexpr".
+
+cout << tuple_size<decltype(third)>::value << "\n"; // prints: 3
+
+// tuple_cat fügt die Elemente eines Tupels aneinander (in der selben Reihenfolge).
+
+auto concatenated_tuple = tuple_cat(first, second, third);
+// concatenated_tuple wird zu = (10, 'A', 1e9, 15, 11, 'A', 3.14141)
+
+cout << get<0>(concatenated_tuple) << "\n"; // Ausgabe: 10
+cout << get<3>(concatenated_tuple) << "\n"; // Ausgabe: 15
+cout << get<5>(concatenated_tuple) << "\n"; // Ausgabe: 'A'
+
+
+///////////////////////////////////
+// Logische- und Bitoperatoren
+//////////////////////////////////
+
+// Die meisten Operatoren in C++ entsprechen denen aus anderen Sprachen
+
+// Logische Operatoren.
+// C++ verwendet so genannte "Short-circuit" Evaluierung für Boolean-Ausdrücke.
+// Das zweite Argument wird ausgeführt bzw. evaluiert, wenn das erste Argument genügt,
+// um den Ausdruck zu bestimmen.
+
+true && false // Führt **logisches und** aus.
+true || false // Führt **logisches oder** aus.
+! true // Führt **logisches nicht** aus.
+
+// Anstelle von Symbolen können auch Schlüsselwörter verwendet werden.
+true and false // Führt **logisches und** aus.
+true or false // Führt **logisches oder** aus.
+not true // Führt **logisches nicht** aus.
+
+// Bitoperationen
+
+// **<<** Links-Shift
+// **>>** Rechts-Shift
+
+~4 // Führt bitweises nicht aus.
+4 | 3 // Führt bitweises oder aus.
+4 & 3 // Führt bitweises und aus.
+4 ^ 3 // Führt bitweises xor aus.
+
+// Gleichwertige Schlüsselwörter:
+compl 4 // Führt bitweises nicht aus.
+4 bitor 3 // Führt bitweises oder aus.
+4 bitand 3 // Führt bitweises und aus.
+4 xor 3 // Führt bitweises xor aus.
+
+
+```
+Weiterführende Literatur:
+
+* Aktuelle Sprachen-Referenz [CPP Reference](http://cppreference.com/w/cpp).
+* Zusätzliches: [CPlusPlus](http://cplusplus.com).
+* Grundlagen Tutorial: [TheChernoProject - C++](https://www.youtube.com/playlist?list=PLlrATfBNZ98dudnM48yfGUldqGD0S4FFb).
diff --git a/de-de/c-de.html.markdown b/de-de/c-de.html.markdown
new file mode 100644
index 00000000..f9090518
--- /dev/null
+++ b/de-de/c-de.html.markdown
@@ -0,0 +1,869 @@
+---
+language: c
+filename: learnc-de.c
+contributors:
+ - ["caminsha", "https://github.com/caminsha"]
+lang: de-de
+---
+
+Ach, C. Immer noch **die** Sprache für modernes High-Performance Computing.
+
+C ist wahrscheinlich die Programmiersprache mit dem niedrigsten Abstraktionsnvieau,
+welche die meisten Programmierer je brauchen werden.
+Die Geschwindigkeit von C ist enorm, allerdings muss man sich stets der
+manuellen Speicherverwaltung bewusst sein.
+
+
+> **Über Compiler Optionen**
+>
+> Standardmäßig sind `gcc` und `clang` ziemlich ruhig bezüglich Warnungen und
+> Fehlern, obwohl dies sehr nützliche Informationen sein können. Es wird
+> empfohlen, strengere Compiler Optionen zu verwenden. Hier sind einige empfohlene
+> Standards:
+> `-Wall -Wextra -Werror -O2 -std=c99 -pedantic`
+>
+> Da gewisse Optionen (inbesondere der C-Standard) sehr stark vom Projekt
+> abhängen, lohnt es sich, wenn die unterschiedlichen Optionen genauer
+> angeschaut werden. Eine Übersicht über die Compiler-Optionen findet man unter
+> [diesem](https://stackoverflow.com/questions/3375697/useful-gcc-flags-for-c) Stackoverflow-Beitrag.
+>
+> Für weitere Informationen, was diese und weitere Optionen genau machen,
+> sollte die Man-Page des C-Compilers aufgerufen werden (z.B. `man 1 gcc`).
+> Alternativ kann auch online nach den unterschiedlichen Optionen gesucht werden.
+
+```c
+// einzeilige Kommentare starten mit // - nur in C99 und später vorhanden.
+
+/*
+mehrzeilige Kommentare sehen so aus. Diese funktionieren auch in C89
+*/
+
+/*
+mehrzeilige Kommentare können nicht verschachtelt werden /* Sei Vorsichtig! */ // Kommentar endet auf dieser Linie ...
+*/ // ... nicht bei dieser!
+
+// Konstanten: #define <keyword>
+// Konstanten werden laut der Konvention immer in GROSSBUCHSTABEN geschrieben
+#define DAYS_IN_YEAR 365
+
+// Konstanten können auch als Aufzählungskonstanten (Enums) definiert werden.
+// Alle Anweisungen müssen mit einem Semikolon beendet werden.
+enum days {SUN = 1, MON, TUE, WED, THU, FRI, SAT};
+// MON wird automatisch zu 2, TUE zu 3 etc.
+
+// Importiere Header-Dateien mit #include
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+// Dateien, welche zwischen <spitzen Klammern> stehen, sind Header-Dateien aus
+// der C-Standard-Bibliothek.
+// Für deine eigenen Header müssen Anführungszeichen verwendet werden, z.B.:
+// #include "mein_header.h"
+
+// Funktionssignaturen werden entweder vorher in einer .h-Datei deklariert oder
+// am Anfang der .c-Datei.
+void function_1();
+int funkcion_2(void);
+
+// Es muss ein Funktionsprototyp deklariert werden vor der `main()` Funktion,
+// wenn die Funktion nach der `main()` Funktion gebraucht wird.
+int add_two_ints(int x1, int x2); // Funktionsprototyp
+// Auch wenn der Ausdrck `int add_two_ints(int, int)` auch valid wäre,
+// ist es empfohlen, dass man die Namen der Argumente hinschreibt für eine
+// einfachere Analyse.
+
+// Der Einstiegspunkt deines Programms ist eine Funktion mit dem Namen main und
+// einem Integer als Rückgabewert.
+int main(void) {
+ // dein Programm
+}
+
+// Die Kommandozeilenargumente, welche gebraucht werden, damit dein Programm
+// läuft, werden als Argumente der `main`-Funktion mitgegeben.
+// argc (argument counter) steht für die Anzahl von Argumenten.
+// Der Programmname ist das erste Argument.
+// argv (argument vector) ist ein Array von Zeichenarrays, welche die
+// Argumente beinhaltet.
+// argv[0] = Name des Programms
+// argv[1] = erstes Argument usw.
+int main (int argc, char** argv) {
+ // Ausgabe mit Hilfe von printf (print formatted)
+ // %d ist ein Integer.
+ // \n steht für eine neue Zeile
+ printf("%d\n",0); // => Gibt 0 aus.
+
+ ////////////////////////////////////////////////
+ // Operatoren
+ ////////////////////////////////////////////////
+
+ // Kurzschreibweise für mehrere Deklarationen
+ int i1 = 1, i2 = 2;
+ flaot f1 = 1.0, f2 = 2.0;
+
+ int b,c;
+ b = c = 0;
+
+ // Arithmetik ist unkompliziert
+ 1 + 2; // => 3
+ 2 - 1; // => 1
+ 2 * 1; // => 2
+ 1 / 2; // 0 (0.5, aber abgeschnitten, da es int sind.)
+
+ // Man muss mindestens ein Integer zu einen float konvertieren, damit man als
+ // Resultat eine Gleitkommazahl erhält.
+ (float)1 / 2; // => 0.5f
+ 1 / (double)2; // => 0.5 // das gleiche mit dem Typ `double`
+ 1.0 / 2.0; // => 0.5, plus oder minus Epsilon
+ // Gleitkommazahlen und deren Berechnungen sind nicht exakt.
+
+ // Es gibt auch die Möglichkeit, Modulo zu rechnen
+ 11 % 3; // => 2
+
+ // Vergleichsoperatoren sind vielleicht schon bekannt, aber in C gibt es
+ // keinen Boolean-Typ. In C verwenden wir `int`. (Oder _Bool oder bool in C99)
+ // 0 ist falsch, alles andere ist wahr (Die Vergleichsoperatoren ergeben
+ // immer 1 oder 0.
+ 3 == 2; // => 0 (falsch)
+ 3 != 2; // => 1 (wahr)
+ 3 > 2; // => 1
+ 3 < 2; // => 0
+ 2 <= 2; // => 1
+ 2 >= 2; // => 1
+
+ // C ist nicht Python - Vergleiche können nicht einfach verkettet werden.
+ // Warnung: die folgende Zeile wird kompilieren, aber es bedeutet `(0 < a) < 2`.
+ // Dieser Ausdruck ist immer wahr, weil (0 < a) kann entweder 1 oder 0 sein.
+ // In diesem Falle ist es 1, weil (0 < 1).
+ int zwischen_0_und_2 = 0 < a < 2;
+ // Benutze stattdessen folgende Schreibweise:
+ int zwischen_0_und_2 = 0 < a && a < 2;
+
+ // Logik funktioniert auch mit ints
+ !3; // => 0 (logisches Nicht)
+ !0; // => 1
+ 1 && 1; // => 1 (logisches Und)
+ 0 && 1; // => 0
+ 0 || 1; // => 1 (logisches Oder)
+ 0 || 0; // => 0
+
+ // Bedingter ternärer Ausdruck ( ? : )
+ int e = 5;
+ int f = 10;
+ int z;
+ z = ( e > f ) ? e : f; // => // => 10 "wenn e > f ist, gib e zurück, sonst f."
+
+ // Inkrementierungs- und Dekrementierungsoperatoren
+ int j = 0;
+ int s = j++; // gib j zurück und erhöhe danach j. (s = 0, j = 1)
+ s = ++j; // erhöhe zuerst j und gib dann j zurück (s = 2, j = 2)
+ // das gleiche gilt für j-- und --j
+
+ // Bitweise Operatoren
+ ~0x0F; // => 0xFFFFFFF0 (Bitweise Negation, "Einer-Komplement",
+ // Beispielresultat für 32-Bit int)
+ 0x0F & 0xF0; // => 0x00 (Bitweises UND)
+ 0x0F | 0xF0; // => 0xFF (Bitweises ODER)
+ 0x04 ^ 0x0F; // => 0x0B (Bitweises XOR)
+ 0x01 << 1; // => 0x02 (Bitweises Linksverschiebung (left shift) (um 1))
+ 0x02 >> 1; // => 0x01 (Bitweises Rechtsverschiebung (right shift) (um 1))
+
+ // Sei vorsichtig beim Shift mit vorzeichenbehafteten Integern
+ // folgende Ausdrücke sind nicht definiert:
+ // - Verschiebung in das Vorzeichenbit (int a = 1 << 31)
+ // - Linksshift einer negativen Zahl (int a = -1 << 2)
+ // - Shift um einen Offset, welcher >= die Breite des linken Ausdrucks ist.
+ // int a = 1 << 32; // undefiniertes Verhalten, wenn int 32-Bit ist.
+
+
+ ////////////////////////////////////////////////
+ // Typen
+ ////////////////////////////////////////////////
+
+ // Compiler, welche nicht C99-kompatibel sind, verlangen, dass sämtliche
+ // Variablen zu Beginn des Blocks deklariert werden.
+ // C99-Konforme Compiler erlauben die Variablendeklaration an dem Punkt, an
+ // welchem die Variable verwendet wird.
+ // Wir deklarieren die Variablen dynamisch im Code um die Lesbarkeit im
+ // Tutorial zu verbessern.
+
+ // integer sind normalerweise 4 Bytes groß
+ int x_int = 0;
+
+ // shorts sind normalerweise 2 Bytes groß
+ short x_short = 0;
+
+ // chars sind garantiert 1 Byte groß
+ char x_char = 0;
+ char y_char = 'y'; // Charakterliterale werden mit '' gekennzeichnet.
+
+ // longs sind oft 4 bis 8 Bytes groß. long long sind garantiert mindestens
+ // 8 Bytes groß.
+ long x_long = 0;
+ long long x_long_long = 0;
+
+ // floats sind normalerweise 32-Bit Gleitkommazahlen
+ float x_float = 0.0f; // 'f'-Suffix beschreibt eine Gleitkommazahl.
+
+ // doubles sind normalerweise 64-Bit Gleitkommazahlen
+ double x_double = 0.0; // echte Zahlen ohne Suffix sind vom Typ double
+
+ // integer-Typen können vorzeichenlos (unsigned) sein
+ // (größer oder kleiner als 0)
+ unsigned short ux_short;
+ unsigned int ux_int;
+ unsigned long long ux_long_long;
+
+ // Zeichen innerhalb von einfachen Anführungszeichen sind Integers im
+ // Maschinenzeichensatz
+ '0'; // => 48 im ASCII-Zeichensatz
+ 'A'; // => 65 im ASCII-Zeichensatz
+
+ // sizeof(T) gibt die Größe einer Variablen des Typen T in Bytes zurück.
+ // sizeof(obj) ergibt die Größe des Ausdrucks (Variable, Literal usw.)
+
+ printf("%zu\n", sizeof(int)); // => 4 (auf den Rechnern mit einem 4-Byte-Wort)
+
+ // Wenn das Argument des `sizeof`-Operator ein Ausdruck ist, dann wird das
+ // Argument nicht ausgewertet (außer Arrays mit variabler Länge)
+ // Der Wert, der in diesem Fall zurückgegeben wird, ist eine Konstante zur
+ // Kompillierzeit.
+
+ int a = 1;
+ //size_t ist ein vorzeichenloser Integer Typ mit mindestens 2 Byte um die
+ // Größe eines Objekts zu repräsentieren.
+ size_t size = sizeof(a++); // a++ wird nicht ausgewertet
+ printf("sizeof(a++) = %zu, wobei a=%d ist\n", size, a);
+ // Gibt "sizeof(a++) = 4, wobei a=1 ist" aus (mit einer 32-Bit-Architektur)
+
+ // Arrays müssen mit einer Größe initialisiert werden.
+ char my_char_array[20]; // Dieses Array beinhaltet 1 * 20 = 20 Bytes
+ int my_int_array[20]; // Dieses Array beinhaltet 4 * 20 = 80 Bytes.
+ // unter der Voraussetzung eines 4-Byte-Worts.
+
+ // Ein Array kann auf diese Weise mit 0 initialisiert werden.
+ char my_array[20] = {0};
+ // Hierbei ist der Teil "{0}" der "Array Initialisierer".
+ // Beachte, dass die Länge des Arrays nicht explizit definiert werden muss,
+ // wenn er auf derselben Linie initialisiert wird.
+ // Folgende Deklaration ist gleichwertig:
+ char my_array[] = {0};
+ // Allerdings muss die Länge des Arrays dann zur Laufzeit ausgewertet werden:
+ size_t my_array_size = sizeof(my_array) / sizeof(my_array[0]);
+ // WARNUNG: Wenn dieser Ansatz gewählt wird, muss man sicherstellen, dass die
+ // Größe des Arrays ermittelt werden *bevor* dieser einer Funktion als
+ // Argument weitergegeben wird (siehe Diskussion weiter unten), weil Arrays
+ // einer Funktion nur als Zeiger übergeben werden. => Das obere Statement
+ // würde innerhalb einer Funktion ein falsches Resultat liefern.
+
+ // Das Indexieren eines Arrays funktioniert wie in anderen Sprache - resp.
+ // in anderen Sprachen funktioniert es gleich wie in C.
+ my_array[0]; // => 0
+
+ // Arrays sind veränderbar; es ist nur Arbeitsspeicher!
+ my_array[1] = 2;
+ printf("%d\n", my_array[1]); // => 2
+
+ // In C99 (und als optionales Feature in C11) können Arrays mit variabler
+ // Länge deklariert werden. Die Größe eines solchen Array muss eine Konstante
+ // zur Kompilierzeit sein.
+ printf("Geben Sie die Arraygröße an: "); //Frag den Benutzer nach
+ // der Arraygröße
+ int array_size;
+ fcsanf(stdin, "%d", &array_size);
+ int var_length_array[array_size]; // deklariere Array mit variabler Länge
+ printf("sizeof array =%zu\n", sizeof var_length_array);
+
+ // Zum Beispiel:
+ // > Geben Sie die Arraygröße an: 10
+ // > sizeof array = 40
+
+ // Strings sind lediglich Arrays von `chars`, welche mit einem Null-Byte
+ // (0x00) beendet werden. In Strings wird das Nullbyte durch das Zeichen \0
+ // repräsentiert. Wir müssen das Null-Byte nicht angeben in String-Literalen;
+ // der Compiler fügt es am Ende des Array automatisch hinzu.
+ char a_string[20] = "Das ist ein String";
+ printf("%s\n", a_string); // %s formattiert einen String
+
+ printf("%d\n", a_string[18]); // => 0
+ // Hier ist das Byte #19 0 (wie auch Byte #20)
+
+ // Wenn wir Zeichen zwischen einfachen Anführungszeichen haben, ist es ein
+ // Zeichenliteral vom Typ int und *nicht* char. (aus historischen Gründen)
+ int cha = 'a'; // Ok
+ char chb = 'a'; // auch ok (implizite Umwandlung von int zu char)
+
+ // Mehrdimensionale Arrays:
+ int multi_array[2][5] = {
+ {1,2,3,4,5},
+ {6,7,8,9,0}
+ };
+ // Auf Elemente zugreifen:
+ int array_int = multi_array[0][2]; // => 3
+
+ ////////////////////////////////////////////////
+ // Kontrollstrukturen
+ ////////////////////////////////////////////////
+ if (0) {
+ printf("Ich werde nie ausgeführt.");
+ }
+ else if (0) {
+ printf("Ich werde auch nie ausgeführt.");
+ }
+ else {
+ printf("Ich gebe etwas aus.");
+ }
+
+ // While-Schleifen existieren auch
+ int ii = 0;
+ while (ii < 10) { // JEDER Wert unter zehn ist wahr
+ printf("%d, " ii++); //i++ inkrementiert ii NACHDEM der Wert gebraucht
+ // wurde.
+ } // => gibt folgendes aus: "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "
+
+ printf("\n");
+
+ int kk = 0;
+ do {
+ printf("%d, ", kk);
+ } while(++kk < 10); //++kk inkrementiert kk BEVOR der Wert gebraucht wurde.
+ // => gibt folgendes aus: "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "
+
+ printf("\n");
+
+ // In C gibt es auch for-Schleifen
+ int jj;
+ for (jj = 0; jj < 10; jj++) {
+ printf("%d, ", jj);
+ } // => gibt folgendes aus: "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "
+
+ printf("\n");
+
+ // **Merke**
+ // Schleifen und Funktionen müssen einen Rumpf haben. Wenn kein Rumpf gebraucht
+ // wird, kann folgendes gemacht werden:
+ int i;
+ for (i = 0; i <= 5; i++) {
+ ; // Semikolon wird als Rumpf behandelt (Null-Anweisung)
+ }
+ // Alternativ kann auch folgendes geschrieben werden:
+ for (i = 0; i <= 5; i++);
+
+ // Verzweigungen mit mehreren Möglichkeiten: `switch()`
+ switch (a) {
+ case 0: // Labels müssen integrale *konstante* Ausdrücke sein (z.B. Enums)
+ printf("Hey, 'a' ist gleich 0!\n");
+ break; //Wenn du kein break einsetzt, so geht der Kontrollfluss
+ // durch die Labels
+ case 1:
+ printf("Huh, 'a' ist gleich 1!\n");
+ break;
+ // Sei vorsichtig - wenn man das `break` vergisst, werden alle
+ // Anweisungen ausgeführt bis das nächste `break` erscheint.
+ case 3:
+ case 4:
+ printf("Schau mal ... 'a' ist entweder 3 oder 4.\n");
+ break;
+ default:
+ // wenn der Ausdruck `a` auf kein Label zutrifft.
+ fputs("Fehler!\n", stderr);
+ exit(-1);
+ break;
+ }
+
+ ////////////////////////////////////////////////
+ // Typenumwandlung
+ ////////////////////////////////////////////////
+
+ // Jeder Wert in C hat einen bestimmten Typen, aber es ist möglich, ein
+ // Wert in einen anderen Typ umzuwandeln (mit einigen Einschränkungen).
+
+ int x_hex = 0x01; // Es ist möglich, Variablen Hexadezimalwerten zuzuweisen.
+
+ // Bei der Umwandlung zwischen Typen wird versucht, den numerischen Wert
+ // beizubehalten.
+ printf("%d\n", x_hex); // => 1
+ printf("%d\n", (short) x_hex); // => 1
+ printf("%d\n", (char) x_hex); // => 1
+
+ // Typen werden überlaufen (overflow) ohne jegliche Warnung
+ printf("%d\n", (unsigned char) 257); // => 1 (Max char=255 wenn char 8 Bit ist)
+
+ // Um den maximalen Wert eines `char`, `signed char` oder `unsigned char`
+ // herauszufinden, können die Makros `CHAR_MAX`, `SCHAR_MAX` und `UCHAR_MAX`
+ // aus der Header-Datei `<limits.h>` verwendet werden.
+
+ // Integer-Typen können zu Gleitkommazahlen und umgekehrt umgewandelt werden.
+ printf("%f\n", (double) 100); // %f formattiert immer zu einem `double`...
+ printf("%f\n", (flaot) 100); // ... auch mit einem `float`
+ printf("%d\n", (char)100.0);
+
+ ////////////////////////////////////////////////
+ // Zeiger (aka Pointer)
+ ////////////////////////////////////////////////
+
+ // In diesem Tutorial wird das deutsche Wort Zeiger nicht verwendet, da es
+ // bei einer weiteren Recherche einfacher ist, wenn man von Pointern ausgeht.
+ // Außerdem ist der Begriff Pointer auch im deutschen Sprachgebrauch zu finden.
+
+ // Ein Pointer ist eine Variable, welche deklariert wurde, um eine Speicher-
+ // adresse zu speichern. Die Deklaration eines Pointers wird auch zeigen,
+ // auf welche Art von Daten der Pointer zeigt. Man kann die Speicheradresse
+ // von Variablen abrufen und dann mit diesen herumspielen.
+
+ int x = 0;
+ printf("%p\n", (void *)&x); // verwende & um die Adresse der Variable
+ // zu erhalten
+ // %p formattiert einen Objektpointer des Typen void*)
+ // => Gibt eine Adresse im Speicher aus
+
+ // Pointer starten mit einem * zu Beginn der Deklaration.
+ int *px, not_a_pointer; // px ist ein Pointer zu einem int.
+ px = &x; // Speichert die Adresse von x in px
+ printf("%p\n", (void *)px); // => Gibt eine Adresse im Speicher aus
+ printf("%zu, %zu\n", sizeof(px), sizeof(not_a_pointer));
+ // Gibt auf einem typischen 64-Bit-System folgendes aus: "8, 4"
+
+ // Um den Wert einer Adresse, auf welche ein Pointer zeigt, herauszufinden,
+ // muss man vor die Variable ein * setzen, um sie zu dereferenzieren.
+ // Notiz: Ja, es kann verwirrend sein, dass '*' sowohl für das Deklarieren
+ // als auch das Derefenzieren verwendet werden kann.
+ printf("%d\n", *px); // => 0, der Wert von x
+
+ // Man kann den Wert, auf welchen ein Pointer zeigt, auch verändern.
+ // Man muss die Dereferenzierung in Klammern setzen, weil ++ eine höhere
+ // Priorität als * hat.
+ (*px)++; // Inkrementiere den Wert, auf welchen px zeigt, um 1
+ printf("%d\n", *px); // => 1
+ printf("%d\n", x); // => 1
+
+ // Arrays sind eine gute Möglichekit, einen zusammenhängenden Block von
+ // Speicher zu allozieren.
+ int x_array[20]; // deklariert einen Array der Größe 20 (Größe kann
+ // nicht geändert werden.)
+ int xx;
+ for (xx =0; xx < 20; xx++) {
+ x_array[xx] 20 -xx;
+ } // Initialisiere x_array zu 20, 19, 18, ... 2, 1
+
+ // Deklariere ein Pointer des Typs int und initalisiere ihn, um auf `x_array`
+ // zu zeigen.
+ int *x_ptr = x_array;
+ // x_ptr zeigt jetzt auf den ersten Wert innerhalb des Arrays (int 20)
+ // Das funktioniert, weil Arrays oft zu Pointern reduziert werden, welche
+ // auf das erste Element zeigen.
+ // Zum Beispiel: Wenn ein Array einer Funktion mitgegeben wird oder einem
+ // Pointer zugewiesen wird, wird es zu einem Pointer reduziert (implizites Casting)
+ // Ausnahme: Wenn das Array das Argument des Operators `&` ist.
+ int arr[10];
+ int (*ptr_to_arr)[10] = &arr; //`&arr` ist nicht vom Typ `int *`!
+ // Es ist vom Typem "Pointer auf Array" (aus zehn `int`s)
+ // oder wenn das Array ein Stringliteral ist, welches gebraucht wird um ein
+ // `char`-Array zu initialisieren.
+ char other_arr[] = "foobarbazquirk";
+ // oder wenn es das Argument des `sizeof` oder `alignof` Operators ist.
+ int third_array[10];
+ int *ptr = third_array; // gleich wie: `int *ptr = &arr[0]`
+ printf("%zu, %zu\n", sizeof(third_array), sizeof(ptr));
+ // Gibt wahrscheinlich "40, 4" oder "40, 8" aus
+
+ // Pointer werden basierend auf dem Typ in- und dekrementiert
+ // Dies wird Pointer-Arithmetik genannt.
+ printf("%d\n", *(x_ptr + 1)); // => 19
+ printf("%d\n", x_array[1]); // => 19
+
+ // Man kann zusammenhängende Speicherblöcke auch mit der Funktion `malloc`
+ // aus der Standardbibliothek dynamisch allozieren. Der Funktion `malloc`
+ // muss ein Argument des Typs `size_t` übergeben werden, welches bestimmt,
+ // wie viele Bytes alloziert werden sollen. (Normalerweise geschieht dies
+ // aus dem Heap - dies kann auf eingebetteten Systemen unterschiedlichen sein.
+ // Der C Standard sagt nichts darüber.)
+ int *my_ptr = malloc(sizeof(*my_ptr) * 20);
+ for (xx = 0; xx < 20; xx++) {
+ *(my_ptr + xx) = 20 -xx; //my_ptr[xx] = 20-xx
+ } // initialisiere Speicher zu 20, 19, 18, 17, ... 2, 1 (als `int`)
+
+ // Sei vorsichtig beim Übergeben von Benutzerdefinierten Werten an `malloc`.
+ // Wenn du sicher sein willst, kannst du die Funktion `calloc` nutzen, welche
+ // (nicht wie `malloc`) auch den Speicher nullt.
+ int *my_other_ptr = calloc(20, sizeof(int));
+
+ // Merke, dass es in C keinen Standard-Weg gibt, um die Länge eines dynamisch
+ // allozierten Arrays zu bestimmen. Auf Grund dessen sollte eine Variable
+ // erstellt werden, welche sich die Anzahl der Elemente im Array merkt, wenn
+ // die Arrays mehrmals im Programm gebraucht werden.
+ // Weitere Informationen stehen im Abschnitt Funktionen.
+ size_t size = 10;
+ int *my_array = calloc(size, sizeof(int));
+ // Füge dem Array ein Element hinzu
+ size++;
+ my_array = realloc(my_array, sizeof(int) *size);
+ if (my_array == NULL) {
+ // Denke daran, realloc-Fehler zu prüfen
+ return
+ }
+ my_array[10] = 5;
+
+ // Das Dereferenzieren von nicht alloziertem Speicher führt zu einem
+ // Undefinierten Verhalten.
+ printf("%d\n", *(my_ptr + 21)); // Gibt irgendwas aus.
+ // Das Programm kann auch abstürzen
+
+ // Nachdem du fertig mit einem Block bist, welcher `malloc` verwendet hat,
+ // muss der Speicher befreit werden. Ansonsten kann dieser Speicherbereich
+ // niemand nutzen bis dein Programm beendet wird.
+ // Dies wird auch als "Speicherleck" (engl: memory leak) bezeichnet.
+ free(my_ptr);
+
+ // Obwohl Strings normalerweise als Pointer-to-Char (Pointer zum ersten
+ // Zeichen des Arrays) repräsentiert werden, sind Strings Arrays aus `char`s.
+ // Es ist eine gute Praxis, `const char *` zu verwenden, wenn man ein
+ // String-Literal referenziert, da String-Literale nicht modifiziert werden
+ // sollten (z.B. "foo"[0] = 'a' ist ILLEGAL)
+ const char *my_str = "Das ist mein eigener String";
+ printf("%c\n", *my_str); // => D
+
+ // Dies ist nicht der Fall, wenn der String ein Array (möglicherweise mit
+ // einem String-Literal initialisiert) ist, welcher im beschreibbaren Speicher
+ // bleibt, wie zum Beispiel in:
+ char foo[] = "foo";
+ foo[0] = 'a'; // Dies ist legal, foo enthält jetzt "aoo"
+
+ function_1();
+} // Ende der `main`-Funktion
+
+////////////////////////////////////////////////
+// Funktionen
+////////////////////////////////////////////////
+
+// Syntax einer Funktionsdeklaration
+// <rueckgabe_wert> <funktions_name>(<args>)
+
+int add_two_ints(int x1, int x2) {
+ return x1 + x2; // verwendet return, um einen Wert zurückzugeben
+}
+
+/*
+Funktionen werden auf Grund des Wertes aufgerufen (call-by-value). Wenn eine
+Funktion aufgerufen wird, sind die Argumente Kopien der ursprünglichen Werte
+(ausgenommen Arrays). Alles, was man innerhalb einer Funktion mit den Werten
+macht, hat keinen Einfluss auf die Originalwerte als die Funktion aufgerufen
+wurde.
+
+Verwende Pointer, um den Originalinhalt zu bearbeiten.
+
+Beispiel:
+*/
+
+// Eine `void`-Funktion gibt keinen Wert zurück
+void str_reverse(char *str_in) {
+ char tmp;
+ size_t ii = 0;
+ size_t size = strlen(str_in);
+ // `strlen()` ist ein Teil der C Standard-Bibliothek.
+ // Merke: Die Länge, welche von `strlen` zurückgegeben wird, ist ohne den
+ // Null-Byte Terminator.
+ for (ii = 0; i < size /2; ii++) { // in C99 kann man `ii` hier deklarieren.
+ tmp = str_in[ii];
+ str_in[ii] = str_in[size - ii - 1]; //#ii'tes Zeichen vom Ende her
+ str_in[size - ii- 1] = tmp;
+ }
+}
+// Merke: Die `string.h`-Headerdatei muss inkludiert werden, bevor `strlen()`
+// verwendet werden kann.
+
+/*
+char c[] = "Das ist ein Test";
+str_reverse(c);
+printf("%s\n", c), => "tseT nie tsi saD"
+*/
+
+// Weil wir lediglich eine Variable zurückgeben können, kann zum Ändern mehrerer
+// Variablen das Konzept call-by-reference verwendet werden.
+void swap_two_numbers(int *a, int *b) {
+ int temp = *a;
+ *a = *b;
+ *b = temp;
+}
+int first = 10;
+int seconde = 20;
+printf("Erste Zahl: %d\n Zweite Zahl: %d\n", first, second);
+swap_two_numbers(&first, &second);
+printf("Erste Zahl: %d\n Zweite Zahl: %d\n", first, second);
+// Werte sind vertauscht.
+
+/*
+Wenn man Arrays betrachtet, so werden diese immer als Pointer übergeben. Auch
+wenn die Arrays statisch alloziert werden (wie zum Beispiel `arr[10]`), werden
+diese als Pointer zum ersten Element des Arrays übergeben.
+Auch hier soll noch einmal erwähnt werden, dass es keinen Standard gibt, wie die
+Größe eines dynamischen Arrays herausgefunden werden kann.
+*/
+// Die Größe des Arrays muss unbedingt mitgegeben werden.
+// Sonst hat die Funktion keine Ahnung wie groß das Array ist.
+void print_int_arrray(int *arr, size_t size) {
+ int i;
+ for (i = 0; i < size; i++) {
+ printf("arr[%d] ist %d\n", i, arr[i]);
+ }
+}
+
+int my_array[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+int size = 10;
+print_int_array(my_array, size);
+// Wird folgendes ausgeben: "arr[0] ist 1" usw.
+
+// Wenn man auf externe Variable (außerhalb der Funktion) referenziert, sollte
+// man das Schlüsselwort `extern` verwenden.
+int i = 0;
+void test_function() {
+ extern int i; // i braucht nun die externe Variable i
+}
+
+// Das Schlüsselwort `static` macht, dass eine Variable außerhalb der Kompilier-
+// einheit nicht zugreifbar ist. (Auf den meisten Systemen ist eine Kompiliereinheit
+// eine `.c`-Datei.) Das Schlüsselwort `static` kann sowohl bei globalen
+// (zur Kompiliereinheit gehörende) Variablen, Funktionen und Funktionslokale
+// Variablen angewendet werden.
+// Wenn man `static` bei lokalen Variablen verwendet, so ist diese Variable global
+// erreichbar und behält dessen Wert über Funktionsaufrufe hinweg, aber sie ist
+// nur innerhalb der deklarierten Funktion verfügbar. Außerdem werden statische
+// Variablen mit 0 initialisiert, wenn sie nicht mit einem anderen Startwert
+// initialisiert werden.
+// Es ist auch möglich, Funktionen als statisch zu deklarieren, damit diese
+// `private` sind. Privat heißt, dass sie nur in diesem Kontekt sichtbar sind.
+
+
+////////////////////////////////////////////////
+// Benutzerdefinierte Typen und Strukturen (Structs)
+////////////////////////////////////////////////
+
+// `typedef`s können verwendet werden, um Typenaliase zu erstellen.
+typedef int my_type;
+my_type my_type_var = 0;
+
+// Structs sind lediglich Sammlungen von Daten, die Inhalte werden
+// (in der Reihenfolge wie sie geschrieben wurden) sequentiell alloziert.
+struct rectangle {
+ int width;
+ int height;
+};
+
+// Allgemein ist es nicht so, dass folgender Ausdruck wahr ist.
+// sizeof(struct rectangle) == sizeof(int) + sizeof(int)
+// Dies ist so, weil potentiell ein Padding zwischen den Struktur-Inhalten
+// möglich ist). (siehe [1, Englisch])
+
+void function_1() {
+ struct rectangle my_rectangle;
+
+ // Greife auf Struct-Inhalte mit `.` zu.
+ my_rectangle.width = 10;
+ my_rectangle.height = 20;
+
+ // Du kannst Pointer zu Structs deklarieren.
+ struct rectangle *my_rectangle_ptr = &my_rectangle;
+
+ // Verwende Dereferenzierung, um Struct-Inhalte zu bearbeiten
+ (*my_rectangle_ptr).width = 30;
+
+ //Noch besser: Verwende die Kurzschreibweise ->, um die Lesbarkeit zu
+ // verbessern.
+ my_rectangle_ptr->height = 10; // Gleich wie: (*my_rectangle_ptr).height = 10;
+}
+
+// Aus Bequemlichkeitsgründen ist es möglich einem `struct` ein `typedef` hinzuzufügen.
+typedef struct rectangle rect;
+
+int area(rect r) {
+ return r.width * r.height;
+}
+
+// Wenn du große Structs hast, kannst du diese mit dem Pointer kopieren,
+// damit große Kopiervorgänge vermieden werden.
+int area_ptr(const rect *r) {
+ return r->width * r->height;
+}
+
+////////////////////////////////////////////////
+// Funktionspointer
+////////////////////////////////////////////////
+
+/*
+Zur Laufzeit sind Funktionen in einer Speicheradresse gespeichert.
+Funktionspointer sind wie normale Pointer (es wird einfach eine Speicheradresse
+gespeichert). Funktionspointer können verwendet werden, um Funktionen und
+Handler (oder Callback-Funktionen) direkt aufzurufen.
+Wie auch immer, die Syntax kann zu Beginn verwirrend wirken.
+
+Zum Beispiel: Verwende str_reverse von einem Pointer
+*/
+void str_reverse_through_pointer(char *str_in) {
+ // Definiere eine Funktionspointer-Variable, welche f genannt wird.
+ void (*f)(char *); // Signatur sollte genau der Funktion entsprechen.
+ f = &str_reverse; // weise die Adresse der wirklichen Funktion zu
+ // (zur Laufzeit bestimmt)
+ // `f = str_reverse;` würde auch funktionieren, da Funktionen zu Pointern
+ // reduziert werden (ähnlich wie Arrays)
+ (*f)(str_in); // Die Funktion einfach mit dem Pointer aufrufen
+ // f(str_in); // Dies ist eine weitere gültige Alternative um eine Funktion
+ // auzurufen.
+}
+
+/*
+Solange die Signaturen der Funktionen übereinstimmen, kann man sämtliche Funktionen
+demselben Pointer zuweisen. Funktionspointer sind auf Grund der Einfacheit und
+Leserlichkeit normalerweise wie folgt `typedef`d
+*/
+typedef void (*my_fnp_type)(char *);
+// Danach werden diese genutzt, um die wirkliche Pointervariable zu deklarieren.
+// ..
+// my_fnp_type f;
+
+// Spezialzeichen
+// Im folgenden sin die englischen Begriffe jeweils in Klammern geschrieben,
+// da diese Begriffe auch im deutschten Sprachgebrauch verwendet werden.
+'\a'; // Alarmzeichen (alert (bell) character)
+'\n'; // Zeichen für neue Linie (newline character)
+'\t'; // Tab (tab character (left justifies text))
+'\v'; // Vertikaler Tab (vertical tab)
+'\f'; // Neue Seite (new page (form feed))
+'\r'; // Wagenrücklauf (carriage return)
+'\b'; // Backspace-Zeichen (backspace character)
+'\0'; // Null-Byte (NULL character). In C wird dieses Zeichen normalerweise am
+// Ende eines Strings gesetzt.
+// Beispiel: Hallo\n\0. "\0" wird per Konvention verwendet, um das Ende
+// eines Strings zu kennzeichnen.
+'\\'; // Backslash (backslash)
+'\?'; // Fragezeichen (question mark)
+'\''; // einfaches Anführungszeichen (single quote)
+'\"'; // doppeltes Anführungszeichen (double quote)
+'\xhh'; // Hexadezimale Zahl (hexadecimal number.) Beispiel:
+ // '\xb' = Zeichen für vertikalen Tab
+'\0oo'; // Oktalzahl (octal number). Beispiel \013 = Zeichen für vertikalen Tab
+
+//Ausgabeformatierung
+"%d"; // Integer
+"%3d"; // Integer mit einer minimalen Länge von drei Zeichen.
+"%s"; // String
+"%f"; // Gleitkommazahl (float)
+"%ld"; // genauere Gleitkommazahl (long)
+"%3.2f"; // Mindestens drei Zeichen vor und drei nach dem Komma.
+"%7.4s"; // (Kann auch mit Strings gemacht werden)
+"%c"; // einzelnes Zeichen (char)
+"%p"; // Pointer. Merke: man muss den Pointer zu void umwandeln,
+ // bevor `printf` funktioniert.
+"%x"; // Hexadezimal
+"%o"; // Oktalzahl
+"%%"; // Gibt % aus
+
+////////////////////////////////////////////////
+// Reihenfolge der Auswertung von Operatoren
+////////////////////////////////////////////////
+
+//-------------------------------------------------------//
+// Operatoren | Assoziativität //
+//-------------------------------------------------------//
+// () [] -> . | linksassoziativ //
+// ! ~ ++ -- + = *(type)sizeof | rechtsassoziativ //
+// * / % | linksassoziativ //
+// + - | linksassoziativ //
+// << >> | linksassoziativ //
+// < <= > >= | linksassoziativ //
+// == != | linksassoziativ //
+// & | linksassoziativ //
+// ^ | linksassoziativ //
+// | | linksassoziativ //
+// && | linksassoziativ //
+// || | linksassoziativ //
+// ?: | rechtsassoziativ //
+// = += -= *= /= %= &= ^= |= <<= >>= | rechtsassoziativ //
+// , | linksassoziativ //
+//-------------------------------------------------------//
+
+
+////////////////////////////////////////////////
+// Header-Dateien
+////////////////////////////////////////////////
+
+/*
+Header-Dateien sind ein wichtiger Teil von C, da sie eine Verbindung zwischen
+unterschiedlichen C-Quelldateien herstellen. Außerdem vereinfachen Header-Dateien
+den Code und Definitionen, da diese in separaten Dateien geschrieben werden können.
+
+Header-Dateien sind von der Syntax her ähnlich zu C-Quelldateien, allerdings haben
+die Header-Dateien die Dateiendung `.h`. Header-Dateien können im Quellcode mit
+der `#include`-Anweisung eingebunden werden z.B. `#include "beispiel.h". Die
+vorherige Anweisung geht davon aus, dass sich die Header-Datei im selben Ordner
+befindet wie die C-Quelldatei.
+*/
+
+// Eine sichere Möglichkeit, einen Header mehrere Male zu definieren bietet, das
+// folgende Statement. Die mehrfache Definition geschieht, wenn Kreisabhängigkeiten
+// bestehen.
+#ifndef EXAMPLE_H /* Wenn EXAMPLE_H noch nicht definiert wurde */
+#define EXAMPLE_H /* definiere das Makro EXAMPLE_H */
+
+// Es könenn weitere Header innerhalb eines Headers eingebunden werden, was dazu
+// führt, dass diese bereits in anderen Dateien eingebunden wurden. So kann eine
+// Header-Datei in mehreren Dateien eingebunden werden. zum Beispiel:
+#include <string.h>
+
+// Wie in den Quelldateien können auch in den Header-Dateien Makros definiert
+// werden und in anderen Dateien verwendet werden, welche diesen Header einbinden.
+#define EXAMPLE_NAME "Dennis Ritchie"
+
+// Funktionsmakros können auch definiert werden.
+#define ADD(a, b) ((a) + (b))
+
+// Beachte die Klammern, welche um die Argumente geschrieben wurden - diese sind
+// wichtig, damit sichergestellt werden kann, dass a und b nicht unerwartet
+// erweitert werden. Zum Beispiel: `MUL (x,y) (x * y)`; Bei der Verwendung von
+// `MUL(1 + 2, 3)` würde dies wie folgt erweitert werden: `(1 + 2 * 3)`, was zu
+// einem falschen Resultat führt.
+
+// Strukturen und Typendefinitionen können verwendet werden, um die Konsistenz
+// zwischen unterschiedlichen Dateien beizubehalten.
+typedef struct Node {
+ int value;
+ struct Node *next;
+}Node;
+
+// Dies kann auch mit Aufzählungen gemacht werden.
+enum traffic_light_state {GREEN, YELLOW, RED};
+
+// Funktionsprototypen könenn auch in Header-Dateien definiert werden, um die
+// Funktion in unterschiedlichen Dateien zu verwenden, aber dies wird als schlechte
+// Praxis angesehen. Definitionen sollten in einer C-Datei erstellt werden.
+Node create_linked_list(int *value, int length);
+
+// Außer den oben genannten Elementen, sollten weitere Definitionen in einer
+// C-Datei gemacht werden. Übermäßige Includes und Definitionen sollten auch
+// nicht einer Header-Datei gemacht werden. Stattdessen wird es empfohlen, diese
+// in eine separate Header-Datei oder in eine C-Quelldatei zu schreiben.
+
+#endif /* Ende der Präprozessordirektive */
+```
+## Weiterführende Literatur
+
+Das Beste wird es sein, wenn man sich ein Exemplar des Buches
+["The C Programming Language"](https://de.wikipedia.org/wiki/The_C_Programming_Language) besorgt.
+Dieses Buch gilt als **das** Buch über die Programmiersprache C und wurde
+von Dennis Ritchie, dem Erfinder der Programmiersprache C, und Brian Kernighan
+geschrieben.
+Sei vorsichtig, da dieses Buch mittlerweile schon etwas älter ist und gewisse
+Unkorrektheiten (d.h. Ideen, welche nicht mehr als gut empfunden werden.) oder
+mittlerweile geänderte Praktiken enthält. [Hinweis: Das Buch wurde auf Englisch
+geschrieben, es gibt aber auch eine Übersetzung davon]
+
+Eine weitere gute Ressource ist [Learn C The Hard Way](http://learncodethehardway.org/c/).
+[Englisch]
+
+Solltest du Fragen zu C haben, so lies die FAQ [compl.lang.c Frequently Asked Questions](http://c-faq.com).[Englisch]
+
+Außerdem ist es wichtig, eine saubere Einrückung zu verwenden. Des weiteren ist
+es wichtig, dass der Codestil möglichst konsistent ist. Es ist wichtiger, lesbaren
+Code zu schreiben als Code, welcher clever und schnell ist. Es lohnt sich ein
+Blick auf den [Codestil des Linuxkernel](https://www.kernel.org/doc/Documentation/process/coding-style.rst) zu werfen. [Englisch]
+
+[1] [Why isn't sizeof for a struct equal to the sum of sizeof of each member?](http://stackoverflow.com/questions/119123/why-isnt-sizeof-for-a-struct-equal-to-the-sum-of-sizeof-of-each-member)
diff --git a/de-de/clojure-macros-de.html.markdown b/de-de/clojure-macros-de.html.markdown
new file mode 100644
index 00000000..088a29a8
--- /dev/null
+++ b/de-de/clojure-macros-de.html.markdown
@@ -0,0 +1,161 @@
+---
+language: "clojure macros"
+filename: learnclojuremacros-de.clj
+contributors:
+ - ["Adam Bard", "http://adambard.com/"]
+translators:
+ - ["Dennis Keller", "https://github.com/denniskeller"]
+lang: de-de
+---
+
+Wie mit allen Lisps besitzt auch Clojure die inhärente [Homoikonizität](https://en.wikipedia.org/wiki/Homoiconic),
+die dir den vollen Zugang der Sprache gibt, um
+ Code-Generierungsroutinen zu schreiben. Diese werden "Macros" genannt.
+Macros geben dir eine leistungsarke Möglichkeit, die Sprache
+an deine Bedürfnisse anzupassen.
+
+Sei aber vorsichtig, es wird als schlechter Stil angesehen, wenn du
+ein Macro schreibst, obwohl eine Funktion genausogut funktionieren würde.
+Verwende nur dann ein Macro, wenn du Kontrolle darüber brauchst, wann oder ob Argumente in einer Form evaluiert werden.
+
+Wenn du mit Clojure vertraut sein möchtest, stelle sicher, dass du alles in [Clojure in Y Minutes](/docs/clojure/) verstehst.
+
+```clojure
+;; Definiere ein Macro mit defmacro. Dein Macro sollte eine Liste zurückgeben,
+;; die als Clojure Code evaluiert werden kann.
+;;
+;; Dieses Macro ist das Gleiche, als ob du (reverse "Hallo Welt") geschrieben
+;; hättest
+(defmacro my-first-macro []
+ (list reverse "Hallo Welt"))
+
+;; Inspiziere das Ergebnis eines Macros mit macroexpand oder macroexpand-1.
+;;
+;; Beachte, dass der Aufruf zitiert sein muss.
+(macroexpand '(my-first-macro))
+;; -> (#<core$reverse clojure.core$reverse@xxxxxxxx> "Hallo Welt")
+
+;; Du kannst das Ergebnis von macroexpand direkt auswerten.
+(eval (macroexpand '(my-first-macro)))
+; -> (\t \l \e \W \space \o \l \l \a \H)
+
+;; Aber du solltest diese prägnante und funktionsähnliche Syntax verwenden:
+(my-first-macro) ; -> (\t \l \e \W \space \o \l \l \a \H)
+
+;; Du kannst es dir leichter machen, indem du die Zitiersyntax verwendest
+;; um Listen in ihren Makros zu erstellen:
+(defmacro my-first-quoted-macro []
+ '(reverse "Hallo Welt"))
+
+(macroexpand '(my-first-quoted-macro))
+;; -> (reverse "Hallo Welt")
+;; Beachte, dass reverse nicht mehr ein Funktionsobjekt ist, sondern ein Symbol
+
+;; Macros können Argumente haben.
+(defmacro inc2 [arg]
+ (list + 2 arg))
+
+(inc2 2) ; -> 4
+
+;; Aber wenn du versuchst das mit einer zitierten Liste zu machen wirst du
+;; einen Fehler bekommen, weil das Argument auch zitiert sein wird.
+;; Um dies zu umgehen, bietet Clojure einee Art und Weise Macros zu zitieren: `
+;; In ` kannst du ~ verwenden um in den äußeren Bereich zu kommen.
+(defmacro inc2-quoted [arg]
+ `(+ 2 ~arg))
+
+(inc2-quoted 2)
+
+;; Du kannst die normalen destruktuierungs Argumente verwenden. Expandiere
+;; Listenvariablen mit ~@.
+(defmacro unless [arg & body]
+ `(if (not ~arg)
+ (do ~@body))) ; Erinnere dich an das do!
+
+(macroexpand '(unless true (reverse "Hallo Welt")))
+;; ->
+;; (if (clojure.core/not true) (do (reverse "Hallo Welt")))
+
+;; (unless) evaluiert und gibt body zurück, wenn das erste Argument falsch ist.
+;; Andernfalls gibt es nil zurück
+
+(unless true "Hallo") ; -> nil
+(unless false "Hallo") ; -> "Hallo"
+
+;; Die Verwendung Macros ohne Sorgfalt kann viel Böses auslösen, indem es
+;; deine Variablen überschreibt
+(defmacro define-x []
+ '(do
+ (def x 2)
+ (list x)))
+
+(def x 4)
+(define-x) ; -> (2)
+(list x) ; -> (2)
+
+;; Um das zu verhindern kannst du gensym verwenden um einen eindeutigen
+;; Identifikator zu bekommen
+(gensym 'x) ; -> x1281 (oder etwas Ähnliches)
+
+(defmacro define-x-safely []
+ (let [sym (gensym 'x)]
+ `(do
+ (def ~sym 2)
+ (list ~sym))))
+
+(def x 4)
+(define-x-safely) ; -> (2)
+(list x) ; -> (4)
+
+;; Du kannst # innerhalb von ` verwenden um für jedes Symbol automatisch
+;; ein gensym zu erstellen
+(defmacro define-x-hygienically []
+ `(do
+ (def x# 2)
+ (list x#)))
+
+(def x 4)
+(define-x-hygienically) ; -> (2)
+(list x) ; -> (4)
+
+;; Es ist üblich, Hilfsfunktionen mit Macros zu verwenden. Lass uns einige
+;; erstellen, die uns helfen , eine (dumme) arithmetische Syntax
+;; zu unterstützen
+(declare inline-2-helper)
+(defn clean-arg [arg]
+ (if (seq? arg)
+ (inline-2-helper arg)
+ arg))
+
+(defn apply-arg
+ "Bekomme die Argumente [x (+ y)], gebe (+ x y) zurück"
+ [val [op arg]]
+ (list op val (clean-arg arg)))
+
+(defn inline-2-helper
+ [[arg1 & ops-and-args]]
+ (let [ops (partition 2 ops-and-args)]
+ (reduce apply-arg (clean-arg arg1) ops)))
+
+;; Wir können es sofort testen, ohne ein Macro zu erstellen
+(inline-2-helper '(a + (b - 2) - (c * 5))) ; -> (- (+ a (- b 2)) (* c 5))
+
+; Allerdings, brauchen wir ein Macro, wenn wir es zur Kompilierungszeit
+; ausführen wollen
+(defmacro inline-2 [form]
+ (inline-2-helper form))
+
+(macroexpand '(inline-2 (1 + (3 / 2) - (1 / 2) + 1)))
+; -> (+ (- (+ 1 (/ 3 2)) (/ 1 2)) 1)
+
+(inline-2 (1 + (3 / 2) - (1 / 2) + 1))
+; -> 3 (eigentlich, 3N, da die Zahl zu einem rationalen Bruch mit / umgewandelt wird)
+```
+
+### Weiterführende Literatur
+
+[Macros schreiben](http://www.braveclojure.com/writing-macros/)
+
+[Offiziele Docs](http://clojure.org/macros)
+
+[Wann verwendet man Macros?](https://lispcast.com/when-to-use-a-macro/)
diff --git a/de-de/css-de.html.markdown b/de-de/css-de.html.markdown
index c31e73d2..da706e91 100644
--- a/de-de/css-de.html.markdown
+++ b/de-de/css-de.html.markdown
@@ -27,7 +27,7 @@ In diesem Artikel wird am meisten auf generelle Hinweise und die Syntax geachtet
####################*/
/* Eigentlich ist das grundlegende CSS-Statement sehr simpel */
-selektor { eigenschaft: wert; /* mehr eigenschaften...*/ }
+selektor { eigenschaft: wert; /* mehr Eigenschaften...*/ }
/* Der Selektor wird dazu benutzt, ein Element auf der Seite auszuwählen.
@@ -35,7 +35,7 @@ Man kann aber auch alle Elemente auf einer Seite auswählen! */
* { color:red; } /* farbe:rot */
/*
-Angenommen wir haben folgendes Element auf einer Seite:
+Angenommen, wir haben folgendes Element auf einer Seite:
<div class='eine-klasse klasse2' id='eineId' attr='wert' />
*/
@@ -170,7 +170,7 @@ empfohlen ist -->
## Spezifität
Ein Element kann natürlich auch von mehr als einer Regel in einem Stylesheet
-angesprochen werdenm und kann eine Eigenschaft auch öfters als einmal zugewiesen
+angesprochen werden und kann eine Eigenschaft auch öfters als einmal zugewiesen
bekommen. In diesen Fällen gibt es Regeln, die die Spezifität von Selektoren regeln.
Wir haben dieses CSS:
diff --git a/de-de/d-de.html.markdown b/de-de/d-de.html.markdown
index 2b0b38dd..28ecc7ae 100644
--- a/de-de/d-de.html.markdown
+++ b/de-de/d-de.html.markdown
@@ -9,7 +9,7 @@ lang: de-de
---
```c
-// Es war klar dass das kommt...
+// Es war klar, dass das kommt...
module hello;
import std.stdio;
@@ -20,13 +20,13 @@ void main(string[] args) {
}
```
-Wenn du so wie ich bist und viel zeit im Internet verbringst stehen die Chancen gut
-das du schonmal über [D](http://dlang.org/) gehört hast.
-Die D-Sprache ist eine moderne, überall einsetzbare programmiersprache die von Low bis
-High Level verwendet werden kann und dabei viele Stile anbietet.
+Wenn du so wie ich bist und viel Zeit im Internet verbringst, stehen die Chancen
+gut, dass du schonmal über [D](http://dlang.org/) gehört hast.
+Die D-Sprache ist eine moderne, überall einsetzbare programmiersprache die von
+Low bis High Level verwendet werden kann und dabei viele Stile anbietet.
D wird aktiv von Walter Bright und Andrei Alexandrescu entwickelt, zwei super schlaue,
-richtig coole leute. Da das jetzt alles aus dem weg ist - auf zu den Beispielen!
+richtig coole leute. Da das jetzt alles aus dem Weg ist - auf zu den Beispielen!
```c
import std.stdio;
@@ -38,7 +38,7 @@ void main() {
writeln(i);
}
- auto n = 1; // auto um den typ vom Compiler bestimmen zu lassen
+ auto n = 1; // auto um den Typ vom Compiler bestimmen zu lassen
// Zahlenliterale können _ verwenden für lesbarkeit
while(n < 10_000) {
@@ -68,21 +68,22 @@ void main() {
}
```
-Neue Typen können mit `struct`, `class`, `union`, und `enum` definiert werden. Structs und unions
-werden as-value (koppiert) an methoden übergeben wogegen Klassen als Referenz übergeben werden.
-Templates können verwendet werden um alle typen zu parameterisieren.
+Neue Typen können mit `struct`, `class`, `union`, und `enum` definiert werden.
+Structs und unions werden as-value (koppiert) an Methoden übergeben wogegen
+Klassen als Referenz übergeben werden. Templates können verwendet werden um
+alle Typen zu parameterisieren.
```c
// Hier, T ist ein Type-Parameter, Er funktioniert wie Generics in C#/Java/C++
struct LinkedList(T) {
T data = null;
- LinkedList!(T)* next; // Das ! wird verwendet um T zu übergeben. (<T> in C#/Java/C++)
+ LinkedList!(T)* next; // Das ! wird verwendet, um T zu übergeben. (<T> in C#/Java/C++)
}
class BinTree(T) {
T data = null;
- // Wenn es nur einen T parameter gibt können die Klammern um ihn weggelassen werden
+ // Wenn es nur einen T Parameter gibt, können die Klammern um ihn weggelassen werden
BinTree!T left;
BinTree!T right;
}
@@ -97,7 +98,7 @@ enum Day {
Saturday,
}
-// Aliase können verwendet werden um die Entwicklung zu erleichtern
+// Aliase können verwendet werden, um die Entwicklung zu erleichtern
alias IntList = LinkedList!int;
alias NumTree = BinTree!double;
@@ -111,8 +112,8 @@ T max(T)(T a, T b) {
return a;
}
-// Steht ref vor einem Parameter wird sichergestellt das er als Referenz übergeben wird.
-// Selbst bei werten wird es immer eine Referenz sein.
+// Steht ref vor einem Parameter, wird sichergestellt, dass er als Referenz
+übergeben wird. Selbst bei Werten wird es immer eine Referenz sein.
void swap(T)(ref T a, ref T b) {
auto temp = a;
@@ -120,18 +121,18 @@ void swap(T)(ref T a, ref T b) {
b = temp;
}
-// Templates können ebenso werte parameterisieren.
+// Templates können ebenso Werte parameterisieren.
class Matrix(uint m, uint n, T = int) {
T[m] rows;
T[n] columns;
}
-auto mat = new Matrix!(3, 3); // Standardmäßig ist T vom typ Integer
+auto mat = new Matrix!(3, 3); // Standardmäßig ist T vom Typ Integer
```
Wo wir schon bei Klassen sind - Wie wäre es mit Properties! Eine Property
-ist eine Funktion die wie ein Wert agiert. Das gibt uns viel klarere Syntax
+ist eine Funktion, die wie ein Wert agiert. Das gibt uns viel klarere Syntax
im Stil von `structure.x = 7` was gleichgültig wäre zu `structure.setX(7)`
```c
@@ -187,18 +188,17 @@ void main() {
```
Mit properties können wir sehr viel logik hinter unseren gettern
-und settern hinter einer schönen syntax verstecken
+und settern hinter einer schönen Syntax verstecken
-Other object-oriented goodies at our disposal
Andere Objektorientierte features sind beispielsweise
`interface`s, `abstract class` und `override`.
Vererbung funktioniert in D wie in Java:
-Erben von einer Klasse, so viele interfaces wie man will.
+Erben von einer Klasse, so viele Interfaces wie man will.
-Jetzt haben wir Objektorientierung in D gesehen aber schauen
+Jetzt haben wir Objektorientierung in D gesehen, aber schauen
wir uns noch was anderes an.
-D bietet funktionale programmierung mit _first-class functions_
-puren funktionen und unveränderbare daten.
+D bietet funktionale Programmierung mit _first-class functions_
+puren Funktionen und unveränderbaren Daten.
Zusätzlich können viele funktionale Algorithmen wie z.B
map, filter, reduce und friends im `std.algorithm` Modul gefunden werden!
@@ -207,11 +207,11 @@ import std.algorithm : map, filter, reduce;
import std.range : iota; // builds an end-exclusive range
void main() {
- // Wir wollen die summe aller quadratzahlen zwischen
+ // Wir wollen die Summe aller Quadratzahlen zwischen
// 1 und 100 ausgeben. Nichts leichter als das!
- // Einfach eine lambda funktion als template parameter übergeben
- // Es ist genau so gut möglich eine normale funktion hier zu übergeben
+ // Einfach eine Lambda-Funktion als Template Parameter übergeben
+ // Es ist genau so gut möglich eine normale Funktion hier zu übergeben
// Lambdas bieten sich hier aber an.
auto num = iota(1, 101).filter!(x => x % 2 == 0)
.map!(y => y ^^ 2)
@@ -221,13 +221,13 @@ void main() {
}
```
-Ist dir aufgefallen wie wir eine Haskell-Style pipeline gebaut haben
+Ist dir aufgefallen, wie wir eine Haskell-Style Pipeline gebaut haben
um num zu berechnen?
Das war möglich durch die Uniform Function Call Syntax.
-Mit UFCS können wir auswählen ob wir eine Funktion als Methode oder
+Mit UFCS können wir auswählen, ob wir eine Funktion als Methode oder
als freie Funktion aufrufen. Walters artikel dazu findet ihr
[hier.](http://www.drdobbs.com/cpp/uniform-function-call-syntax/232700394)
-Kurzgesagt kann man Funktionen deren erster parameter vom typ A ist, als
+Kurzgesagt kann man Funktionen, deren erster Parameter vom typ A ist, als
Methode auf A anwenden.
Parrallel Computing ist eine Tolle sache, findest du nicht auch?
@@ -239,10 +239,10 @@ import std.math : sqrt;
void main() {
// Wir wollen die Wurzel von jeder Zahl in unserem Array berechnen
- // und dabei alle Kerne verwenden die wir zur verfügung haben
+ // und dabei alle Kerne verwenden, die wir zur verfügung haben
auto arr = new double[1_000_000];
- // Wir verwenden den index und das element als referenz
+ // Wir verwenden den Index und das Element als Referenz
// und rufen einfach parallel auf!
foreach(i, ref elem; parallel(arr)) {
ref = sqrt(i + 1.0);
diff --git a/de-de/dhall-de.html.markdown b/de-de/dhall-de.html.markdown
new file mode 100644
index 00000000..385c88be
--- /dev/null
+++ b/de-de/dhall-de.html.markdown
@@ -0,0 +1,380 @@
+---
+language: Dhall
+contributors:
+ - ["Gabriel Gonzalez", "http://www.haskellforall.com/"]
+translators:
+ - ["Profpatsch", "http://profpatsch.de"]
+filename: learndhall-de.py
+lang: de-de
+---
+
+Dhall ist eine programmierbare Konfigurationssprache und bietet eine
+nicht-repetetive Alternative zu YAML.
+
+Man kann Dhall sehen als: JSON + Funktionen + Typen + Importsystem
+
+Obwohl Dhall programmierbar ist, ist die Sprache nicht
+turingvollständig. Viele von Dhalls Features benutzen diese
+Einschränkung, um stärkere Sicherheitsgarantien zu bieten und besseres
+Tooling zu ermöglichen.
+
+```haskell
+-- einzeiliger Kommentar
+
+{- mehrzeiliger Kommentar
+
+ Unicode funktioniert 🙂
+
+ Diese Datei ist eine valide Dhall-Expression und evaluiert zu einem
+ großen Record, welcher die Ergebnisse jedes Schritts beinhaltet.
+
+ Das Ergebnis kann angezeigt werden, indem man die Datei evaluiert:
+
+ $ dhall --file learndhall.dhall
+
+ {- Kommentare können verschachtelt sein -}
+-}
+
+let greeting = "Hallo, Welt!"
+
+let fruits = "🍋🍓🍍🍉🍌"
+
+let interpolation = "Ein paar leckere Früchte: ${fruits}"
+
+let multilineText {- Inline-Kommentare funktionieren ebenfalls -} =
+ ''
+ In Multiline-Text-Literals wird Whitespace am Anfang der Zeile
+ entfernt.
+
+ Das bedeutet Text kann frei eingerückt oder ausgerückt werden,
+ ohne dass sich der Inhalt des Strings ändert.
+
+ Relative Einrückungen bleiben erhalten.
+
+ Ansonsten wird das Text-Literal verbatim erhalten, ähnlich
+ zu “literal”-Multiline-Strings in YAML.
+ ''
+
+let bool = True
+
+-- Typannotationen für Bindings sind optional, aber hilfreich, also
+-- benutzen wir sie hier.
+let annotation : Bool = True
+
+let renderedBool : Text = if bool then "True" else "False"
+
+-- Natürliche Zahlen sind nicht-negativ und vorzeichenlos.
+let naturalNumber : Natural = 42
+
+-- Integer können negativ sein, brauchen aber ein explizites Vorzeichen.
+let positiveInteger : Integer = +1
+
+let negativeInteger : Integer = -12
+
+let pi : Double = 3.14159265359
+
+{- Identifier dürfen eine große Anzahl an verschiedenen Zeichen
+ beinhalten (wie z.B. Anführungszeichen oder Whitespace), wenn man
+ sie mit Backticks umschließt.
+-}
+let `Avogadro's Number` : Double = 6.0221409e+23
+
+let origin : { x : Double, y : Double } = { x = 0.0, y = 0.0 }
+
+let somePrimes : List Natural = [ 2, 3, 5, 7, 11 ]
+
+{- Ein Schema ist das gleiche wie ein Typ.
+
+ Typnamen beginnen konventionell mit einem Großbuchstaben, was
+ jedoch nicht erzwungen wird.
+-}
+let Profile : Type
+ = { person :
+ { name : Text
+ , age : Natural
+ }
+ , address :
+ { country : Text
+ , state : Text
+ , city : Text
+ }
+ }
+
+let bernd : Profile =
+ { person =
+ { name = "Bernd Lauert"
+ , age = 67
+ }
+ , address =
+ { country = "Deutschland"
+ , state = "Bayern"
+ , city = "Augsburg"
+ }
+ }
+
+let augsburg : Text = bernd.address.city
+
+{- Enum-Alternativen beginnen konventionell auch mit einem
+ Großbuchstaben. Das wird ebenfalls nicht erzwungen.
+-}
+let DNA : Type = < Adenine | Cytosine | Guanine | Thymine >
+
+let dnaSequence : List DNA = [ DNA.Thymine, DNA.Guanine, DNA.Guanine ]
+
+let compactDNASequence : List DNA =
+ let a = DNA.Adenine
+ let c = DNA.Cytosine
+ let g = DNA.Guanine
+ let t = DNA.Thymine
+ in [ c, t, t, a, t, c, g, g, c ]
+
+-- Enums werden transformiert, indem man einen Record mit einem Feld
+-- pro Alternative angibt.
+let theLetterG : Text =
+ merge
+ { Adenine = "A"
+ , Cytosine = "C"
+ , Guanine = "G"
+ , Thymine = "T"
+ }
+ DNA.Guanine
+
+let presentOptionalValue : Optional Natural = Some 1
+
+let absentOptionalValue : Optional Natural = None Natural
+
+let points : List { x : Double, y : Double } =
+ [ { x = 1.1, y = -4.2 }
+ , { x = 4.4, y = -3.0 }
+ , { x = 8.2, y = -5.5 }
+ ]
+
+{- `Natural -> List Natural` ist der Funktionstyp mit Eingabetyp
+ `Natural` und Ausgabetyp `List Natural`.
+
+ Alle Funktionen in Dhall sind Anonyme Funktionen (aka. „Lambdas“),
+ denen man optional einen Namen geben kann.
+
+ Die folgende Funktion beispielsweise ist äquivalent zu diesem
+ Python Code:
+
+ lambda n : [ n, n + 1 ]
+
+ ... und diesem Javascript Code:
+
+ function (n) { return [ n, n + 1 ]; }
+-}
+let exampleFunction : Natural -> List Natural =
+ \(n : Natural) -> [ n, n + 1 ]
+
+-- Dhall unterstützt auch Unicode-Syntax, aber dieses Tutorial nutzt
+-- die ASCII-Syntax.
+let unicodeFunction : Natural → List Natural =
+ λ(n : Natural) → [ n, n + 1 ]
+
+-- Funktionsargumente brauchen keine Klammern.
+let exampleFunctionApplication : List Natural =
+ exampleFunction 2
+
+let functionOfMultipleArguments : Natural -> Natural -> List Natural =
+ \(x : Natural) -> \(y : Natural) -> [ x, y ]
+
+let functionAppliedToMultipleArguments : List Natural =
+ functionOfMultipleArguments 2 3
+
+{- Wie `exampleFunction`, aber wir geben dem Eingabetypen
+ einen Namen, `n`.
+-}
+let namedArgumentType : forall (n : Natural) -> List Natural =
+ \(n : Natural) -> [ n, n + 1 ]
+
+{- Bekommt der Eingabetyp einen Namen, kann man ihn weiter hinten in
+ der gleichen Typdefinition wiederverwenden.
+
+ Das ermöglicht Funktionen, die mit mehr als einem Eingabetypen
+ arbeiten können (aka. „polymorphe“ Funktionen).
+-}
+let duplicate : forall (a : Type) -> a -> List a =
+ \(a : Type) -> \(x : a) -> [ x, x ]
+
+let duplicatedNumber : List Natural =
+ duplicate Natural 2
+
+let duplicatedBool : List Bool =
+ duplicate Bool False
+
+{- Die Sprache hat auch eine handvoll eingebauter polymorpher
+ Funktionen, wie zum Beispiel:
+
+ List/head : forall (a : Type) -> List a -> Optional a
+-}
+let firstPrime : Optional Natural = List/head Natural somePrimes
+
+let functionOfARecord : { x : Natural, y : Natural } -> List Natural =
+ \(args : { x : Natural, y : Natural }) -> [ args.x, args.y ]
+
+let functionAppliedToARecord : List Natural =
+ functionOfARecord { x = 2, y = 5 }
+
+{- Alle Typkonversionen sind explizit.
+
+ `Natural/show` ist eine eingebaute Funktion mit dem Typ:
+
+ Natural/show : Natural -> Text
+
+ ... welche `Natural`s in ihre `Text`-Repräsentation konvertiert.
+-}
+let typeConversion : Natural -> Text =
+ \(age : Natural) -> "Ich bin ${Natural/show age} Jahre alt!"
+
+-- Ein „Template“ ist einfach eine Funktion mit Ausgabetyp `Text`.
+let mitLicense : { year : Natural, copyrightHolder : Text } -> Text =
+ \(args : { year : Natural, copyrightHolder : Text }) ->
+''
+Copyright ${Natural/show args.year} ${args.copyrightHolder}
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+''
+
+-- Template-Instanziierung ist das gleiche wie Funktionsanwendung.
+let templatedLicense : Text =
+ mitLicense { year = 2019, copyrightHolder = "Jane Smith" }
+
+{- Expressions können via URL importiert werden.
+
+ Ähnlich wie in Bash kann man Code aus dem lokalen Dateisystem
+ importieren (wird nicht gezeigt).
+
+ Sicherheitsbewusste Nutzer können via URLs importierte Expressions
+ mit einem semantischen Integritätscheck versehen („pinnen“).
+ Für gepinnte Imports wird der Dhall-Interpreter jeden Versuch
+ vereiteln, auf der Remote-Seite die Expression zu manipulieren.
+ Jedoch werden Änderungen, die den Inhalt der importierten
+ Expression nicht verändern trotzdem akzeptiert.
+
+ Auf diese Weise gepinnte Expressions werden auch in einem
+ Content-Adressable Store lokal gecached (standardmäßig in
+ `~/.cache/dhall`).
+-}
+let Natural/sum : List Natural -> Natural =
+ https://prelude.dhall-lang.org/Natural/sum
+ sha256:33f7f4c3aff62e5ecf4848f964363133452d420dcde045784518fb59fa970037
+
+let twentyEight : Natural = Natural/sum somePrimes
+
+-- Ein „Paket“ ist einfach ein (möglicherweise verschachtelter)
+-- Record, den man importiert.
+let Prelude = https://prelude.dhall-lang.org/package.dhall
+
+let false : Bool = Prelude.Bool.not True
+
+-- Durch das Anhängen von `as Text` wird eine Datei verbatim
+-- importiert und nicht als Dhall-Code interpretiert.
+let sourceCode : Text = https://prelude.dhall-lang.org/Bool/not as Text
+
+-- Environment-Variablen können auch imortiert werden.
+let presentWorkingDirectory = env:PWD as Text
+
+-- Mit `?` kann man eine “Fallback-Expression” angeben, für den Fall
+-- dass ein Import fehlschlägt.
+let home : Optional Text = Some env:HOME ? None Text
+
+-- Fallback-Expressions können auch alternative Imports enthalten.
+let possiblyCustomPrelude =
+ env:DHALL_PRELUDE
+ ? https://prelude.dhall-lang.org/package.dhall
+
+{- Ein ausführliches Beispiel, welches mithilfe der
+ `generate`-Funktion eine Konfiguration für 10 Build-User generiert:
+
+ Prelude.List.generate
+ : Natural -> forall (a : Type) -> (Natural -> a) -> List a
+-}
+let buildUsers =
+ let makeUser = \(user : Text) ->
+ let home = "/home/${user}"
+ let privateKey = "${home}/.ssh/id_ed25519"
+ let publicKey = "${privateKey}.pub"
+ in { home = home
+ , privateKey = privateKey
+ , publicKey = publicKey
+ }
+
+ let buildUser =
+ \(index : Natural) -> makeUser "build${Natural/show index}"
+
+ let Config =
+ { home : Text
+ , privateKey : Text
+ , publicKey : Text
+ }
+
+ in Prelude.List.generate 10 Config buildUser
+
+-- Alle Ergebnisse in einem großen Record
+in { greeting = greeting
+ , fruits = fruits
+ , interpolation = interpolation
+ , multilineText = multilineText
+ , bool = bool
+ , annotation = annotation
+ , renderedBool = renderedBool
+ , naturalNumber = naturalNumber
+ , positiveInteger = positiveInteger
+ , negativeInteger = negativeInteger
+ , pi = pi
+ , `Avogadro's Number` = `Avogadro's Number`
+ , origin = origin
+ , somePrimes = somePrimes
+ , bernd = bernd
+ , augsburg = augsburg
+ , dnaSequence = dnaSequence
+ , compactDNASequence = compactDNASequence
+ , theLetterG = theLetterG
+ , presentOptionalValue = presentOptionalValue
+ , absentOptionalValue = absentOptionalValue
+ , points = points
+ , exampleFunction = exampleFunction
+ , unicodeFunction = unicodeFunction
+ , exampleFunctionApplication = exampleFunctionApplication
+ , functionOfMultipleArguments = functionOfMultipleArguments
+ , functionAppliedToMultipleArguments = functionAppliedToMultipleArguments
+ , namedArgumentType = namedArgumentType
+ , duplicate = duplicate
+ , duplicatedNumber = duplicatedNumber
+ , duplicatedBool = duplicatedBool
+ , firstPrime = firstPrime
+ , functionOfARecord = functionOfARecord
+ , functionAppliedToARecord = functionAppliedToARecord
+ , typeConversion = typeConversion
+ , mitLicense = mitLicense
+ , templatedLicense = templatedLicense
+ , twentyEight = twentyEight
+ , false = false
+ , sourceCode = sourceCode
+ , presentWorkingDirectory = presentWorkingDirectory
+ , home = home
+ , buildUsers = buildUsers
+ }
+```
+
+Mehr Infos und Lernmaterialien gibt es auf der offiziellen Website
+(Englisch), auf der man Dhall auf im Browser ausprobieren kann:
+
+* [https://dhall-lang.org](http://dhall-lang.org/)
diff --git a/de-de/dynamic-programming-de.html.markdown b/de-de/dynamic-programming-de.html.markdown
new file mode 100644
index 00000000..58568b3b
--- /dev/null
+++ b/de-de/dynamic-programming-de.html.markdown
@@ -0,0 +1,77 @@
+---
+category: Algorithms & Data Structures
+name: Dynamic Programming
+contributors:
+ - ["Akashdeep Goel", "http://github.com/akashdeepgoel"]
+translators:
+ - ["Henrik Jürges", "http://github.com/santifa"]
+lang: de-de
+---
+
+# Dynamische Programmierung
+
+## Einführung
+Dynamische Programmierung ist eine leistungsfähige Technik, die zur Lösung
+einer bestimmten Klasse von Problemen verwendet wird.
+Die Idee ist sehr einfach, wenn Sie ein Problem mit der gegebenen Eingabe
+gelöst haben, dann speichern Sie das Ergebnis für die spätere Referenz, um zu
+vermeiden, das gleiche Problem noch einmal zu lösen.
+
+Denken Sie immer daran!
+"Diejenigen, die sich nicht an die Vergangenheit erinnern können,
+sind dazu verdammt, sie zu wiederholen."
+
+## Wege zur Lösung solcher Probleme
+
+1. *Top-Down*: Lösen Sie das gegebene Problem, indem Sie es aufteilen.
+Wenn Sie sehen, dass das Problem bereits gelöst ist, geben Sie einfach die
+gespeicherte Antwort zurück. Wenn es nicht gelöst wurde, lösen Sie es und
+speichern Sie die Antwort. Dieser Ansatz ist leicht zu verfolgen und sehr
+intuitiv. Er wird als Memoization bezeichnet.
+
+2. *Bottom-Up*: Analysieren Sie das Problem und beobachten Sie, in welcher
+Reihenfolge die Teilprobleme gelöst werden können. Beginnen Sie mit der
+Lösung vom trivialen Teilproblem bis zum gegebenen Problem. Dabei wird
+sichergestellt, dass die Teilprobleme vor der Problemlösung gelöst werden.
+Dies wird als Dynamische Programmierung bezeichnet.
+
+## Ein Beispiel für Dynamische Programmierung
+
+Das Problem mit der längsten ansteigenden Subsequenz besteht darin,
+die längste ansteigende Subsequenz einer gegebenen Sequenz zu finden.
+Gegeben die Sequenz `S= {a1, a2, a3, a3, a4,..............., an-1, an }`,
+müssen wir die größte Teilmenge finden, so daß für alle `j` und `i`, `j<i`
+in der Teilmenge `aj<ai` gilt.
+Zuerst müssen wir bei jedem Index i den Wert der längsten Subsequenzen (LSi)
+finden, wobei das letzte Element der Sequenz ai ist. Dann wäre die größte LSi
+die längste Subsequenz in der gegebenen Sequenz. Am Anfang wird der LSi mit
+eins belegt, da ai ein Element der Sequenz (Letztes Element) ist.
+Dann ist für alle `j` mit `j<i` und `aj<ai`, so dass wir den größten LSj finden
+und zum LSi hinzufügen. Der Algorithmus hat eine Laufzeit von *O(n2)*.
+
+Pseudocode zur Bestimmung der Länge der am längsten ansteigenden Subsequenz:
+Die Komplexität des Algorithmus könnte durch eine bessere Datenstruktur anstelle
+von Arrays reduziert werden. Das Speichern von Vorgänger-Array's und Variablen
+wie `largest_sequences_so_far` und dessen Index würde eine Menge Zeit sparen.
+
+Ein ähnliches Konzept könnte auch bei der Suche nach dem längsten Weg
+in gerichteten azyklischen Graphen angewandt werden.
+```python
+for i=0 to n-1
+ LS[i]=1
+ for j=0 to i-1
+ if (a[i] > a[j] and LS[i]<LS[j])
+ LS[i] = LS[j]+1
+for i=0 to n-1
+ if (largest < LS[i])
+```
+
+### Einige bekannte DP Probleme
+
+- [Floyd Warshall Algorithm - Tutorial and C Program source code](http://www.thelearningpoint.net/computer-science/algorithms-all-to-all-shortest-paths-in-graphs---floyd-warshall-algorithm-with-c-program-source-code)
+- [Integer Knapsack Problem - Tutorial and C Program source code](http://www.thelearningpoint.net/computer-science/algorithms-dynamic-programming---the-integer-knapsack-problem)
+- [Longest Common Subsequence - Tutorial and C Program source code](http://www.thelearningpoint.net/computer-science/algorithms-dynamic-programming---longest-common-subsequence)
+
+## Online Ressourcen
+
+* [codechef](https://www.codechef.com/wiki/tutorial-dynamic-programming)
diff --git a/de-de/edn-de.html.markdown b/de-de/edn-de.html.markdown
new file mode 100644
index 00000000..2434d1bd
--- /dev/null
+++ b/de-de/edn-de.html.markdown
@@ -0,0 +1,112 @@
+---
+language: edn
+filename: learnedn-de.edn
+contributors:
+ - ["Jason Yeo", "https://github.com/jsyeo"]
+ - ["Jonathan D Johnston", "https://github.com/jdjohnston"]
+translators:
+ - ["Dennis Keller", "https://github.com/denniskeller"]
+lang: de-de
+---
+
+Extensible Data Notation (EDN) ist ein Format für serialisierte Daten.
+
+EDN ist ein Subset der von Clojure verwendeten Syntax. Das Lesen von Daten, die durch EDN definiert werden, ist
+sicherer als das, was durch die vollständige Clojure-Syntax definiert wird, insbesondere von nicht
+vertrauenswürdigen Quellen. EDN ist beschränkt auf Daten, kein Code. Es ist ähnlich in seinen Zielen zu JSON.
+Obwohl es mehr in Clojure verwendet wird, gibt es verschiedene Implementationen von EDN in vielen
+verschiedenen anderen Sprachen.
+
+Der Hauptvorteil von EDN im Gegensatz zu JSON und YAML ist, dass es erweiterbar ist.
+Wir werden später sehen wie es erweitert werden kann.
+
+```clojure
+; Kommentare starten mit einem Semikolon.
+; Alles nach dem Semikolon wird ignoriert.
+
+;;;;;;;;;;;;;;;;;;;
+;;; Basistypen ;;;
+;;;;;;;;;;;;;;;;;;;
+
+nil ; auch bekannt in anderen Sprachen als null
+
+; Booleans
+true
+false
+
+; Strings werden in Gänsefüßchen eingeschlossen.
+"hungarian breakfast"
+"farmer's cheesy omelette"
+
+; Charaktere werden einem Backslash vorangestellt
+\g \r \a \c \e
+
+; Schlüsselwörter beginnen mit einem Doppelpunkt. Sie verhalten sich wie Enums.
+; Ähnlich, wie Symbole in Ruby.
+:eggs
+:cheese
+:olives
+
+; Symbole werden verwendet um Identifier zu repräsentieren. Sie beginnen mit einem #.
+; Du kannst einen Namespace für Symbole nutzen, wenn du / verwendest. Egal was / vorangestellt wird
+; ist der Namespace dieses Namens.
+#spoon
+#kitchen/spoon ; nicht das selbe, wie #spoon
+#kitchen/fork
+#github/fork ; damit kannst du nicht essen
+
+; Integers und Floats
+42
+3.14159
+
+; Listen sind Sequenzen von Werten
+(:bun :beef-patty 9 "yum!")
+
+; Vektoren erlauben zufälligen Zugriff
+[:gelato 1 2 -2]
+
+; Maps sind assoziative Datenstrukturen, die einen Schlüssel mit einem Wert verbinden.
+{:eggs 2
+ :lemon-juice 3.5
+ :butter 1}
+
+; Du bist nicht beschränkt ausschließlich Schlüsselwörter als Schlüssel zu verwenden.
+{[1 2 3 4] "tell the people what she wore",
+ [5 6 7 8] "the more you see the more you hate"}
+
+; Du kannst Kommas für eine bessere Lesbarkeit verwenden. Sie werden wie Leerraum behandelt.
+; Sets sind Sammlungen, die eindeutige Elemente enthalten.
+#{:a :b 88 "huat"}
+
+;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; markierte Elemente ;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;
+
+; EDN kann erweitert werden, indem Elemente mit # Symbolen makiert werden.
+
+#MyYelpClone/MenuItem {:name "eggs-benedict" :rating 10}
+
+; Lass mich das mit einem Clojure Beispiel erklären.
+; Angenommen ich möchte dieses Stück EDM in einen MenuItem record umwandeln.
+(defrecord MenuItem [name rating])
+
+; Um EDN in clojure Werte umzuwandeln, muss ich den eingebauten EDN Leser
+; edn/read-string verwenden
+
+(edn/read-string "{:eggs 2 :butter 1 :flour 5}")
+; -> {:eggs 2 :butter 1 :flour 5}
+
+; Definiere die Leserfunktion, um markierte Elemente zu transformieren
+; und übergebe eine Map, die Tags den Lesefunktionen als edn / read-string zuweisen
+
+(edn/read-string {:readers {'MyYelpClone/MenuItem map->menu-item}}
+ "#MyYelpClone/MenuItem {:name \"eggs-benedict\" :rating 10}")
+; -> #user.MenuItem{:name "eggs-benedict", :rating 10}
+
+```
+
+# Referenzen
+
+- [EDN spec](https://github.com/edn-format/edn)
+- [Implementationen](https://github.com/edn-format/edn/wiki/Implementations)
+- [makierte Elemente](http://www.compoundtheory.com/clojure-edn-walkthrough/)
diff --git a/de-de/elm-de.html.markdown b/de-de/elm-de.html.markdown
new file mode 100644
index 00000000..08832327
--- /dev/null
+++ b/de-de/elm-de.html.markdown
@@ -0,0 +1,376 @@
+---
+language: Elm
+filename: learnelm.elm
+contributors:
+ - ["Max Goldstein", "http://maxgoldste.in/"]
+translators:
+ - ["waynee95", "https://waynee95.me"]
+lang: de-de
+---
+
+Elm ist eine pure funktionale Programmiersprache. Mit Elm werden GUIs
+(grafische Benutzeroberfläche) für Webanwendungen erstellt. Durch die statische
+Typisierung kann Elm viele Fehler schon bei der Kompilierung abfangen. Ein
+Hauptmerkmal von Elm sind die ausführlichen und gut erklärten Fehlermeldungen.
+
+```haskell
+-- Einzeilige Kommentare beginnen mit 2 Bindestrichen.
+{- So wird ein mehrzeiliger Kommentar angelegt.
+{- Diese können auch verschachtelt werden. -}
+-}
+
+{-- Die Grundlagen --}
+
+-- Arithmetik
+1 + 1 -- 2
+8 - 1 -- 7
+10 * 2 -- 20
+
+-- Zahlen ohne Punkt sind entweder vom Typ Int oder Float.
+33 / 2 -- 16.5 mit Division von Gleitkommazahlen
+33 // 2 -- 16 mit ganzzahliger Division
+
+-- Exponenten
+5 ^ 2 -- 25
+
+-- Boolsche Werte
+not True -- False
+not False -- True
+1 == 1 -- True
+1 /= 1 -- False
+1 < 10 -- True
+
+-- Strings (Zeichenketten) und Zeichen
+"Das hier ist ein String."
+'a' -- Zeichen
+
+-- Strings können konkateniert werden.
+"Hello " ++ "world!" -- "Hello world!"
+
+{-- Listen und Tupel --}
+
+-- Jedes Element einer Liste muss vom gleichen Typ sein. Listen sind homogen.
+["the", "quick", "brown", "fox"]
+[1, 2, 3, 4, 5]
+-- Das zweite Beispiel kann man auch mit Hilfe der "range" Funktion schreiben.
+List.range 1 5
+
+-- Listen werden genauso wie Strings konkateniert.
+List.range 1 5 ++ List.range 6 10 == List.range 1 10 -- True
+
+-- Mit dem "cons" Operator lässt sich ein Element an den Anfang einer Liste anfügen.
+0 :: List.range 1 5 -- [0, 1, 2, 3, 4, 5]
+
+-- Die Funktionen "head" und "tail" haben als Rückgabewert den "Maybe" Typ.
+-- Dadurch wird die Fehlerbehandlung von fehlenden Elementen explizit, weil
+-- man immer mit jedem möglichen Fall umgehen muss.
+List.head (List.range 1 5) -- Just 1
+List.tail (List.range 1 5) -- Just [2, 3, 4, 5]
+List.head [] -- Nothing
+-- List.funktionsName bedeutet, dass diese Funktion aus dem "List"-Modul stammt.
+
+-- Tupel sind heterogen, jedes Element kann von einem anderen Typ sein.
+-- Jedoch haben Tupel eine feste Länge.
+("elm", 42)
+
+-- Das Zugreifen auf Elemente eines Tupels geschieht mittels den Funktionen
+-- "first" und "second".
+Tuple.first ("elm", 42) -- "elm"
+Tuple.second ("elm", 42) -- 42
+
+-- Das leere Tupel, genannt "Unit", wird manchmal als Platzhalter verwendet.
+-- Es ist das einzige Element vom Typ "Unit".
+()
+
+{-- Kontrollfluss --}
+
+-- Eine If-Bedingung hat immer einen Else-Zweig und beide Zweige müssen den
+-- gleichen Typ haben.
+if powerLevel > 9000 then
+ "WHOA!"
+else
+ "meh"
+
+-- If-Bedingungen können verkettet werden.
+if n < 0 then
+ "n is negative"
+else if n > 0 then
+ "n is positive"
+else
+ "n is zero"
+
+-- Mit dem Mustervergleich (pattern matching) kann man bestimmte Fälle direkt
+-- behandeln.
+case aList of
+ [] -> "matches the empty list"
+ [x]-> "matches a list of exactly one item, " ++ toString x
+ x::xs -> "matches a list of at least one item whose head is " ++ toString x
+-- Mustervergleich geht immer von oben nach unten. Würde man [x] als letztes
+-- platzieren, dann würde dieser Fall niemals getroffen werden, weil x:xs diesen
+-- Fall schon mit einschließt (xs ist in dem Fall die leere Liste).
+
+-- Mustervergleich an einem Maybe Typ.
+case List.head aList of
+ Just x -> "The head is " ++ toString x
+ Nothing -> "The list was empty."
+
+{-- Funktionen --}
+
+-- Die Syntax für Funktionen in Elm ist minimal. Hier werden Leerzeichen anstelle
+-- von runden oder geschweiften Klammern verwendet. Außerdem gibt es kein "return"
+-- Keyword.
+
+-- Eine Funktion wird durch ihren Namen, einer Liste von Parametern gefolgt von
+-- einem Gleichheitszeichen und dem Funktionskörper angegeben.
+multiply a b =
+ a * b
+
+-- Beim Aufruf der Funktion (auch Applikation genannt) werden die Argumente ohne
+-- Komma übergeben.
+multiply 7 6 -- 42
+
+-- Partielle Applikation einer Funktion (Aufrufen einer Funktion mit fehlenden
+-- Argumenten). Hierbei entsteht eine neue Funktion, der wir einen Namen geben.
+double =
+ multiply 2
+
+-- Konstanten sind Funktionen ohne Parameter.
+answer =
+ 42
+
+-- Funktionen, die Funktionen als Parameter haben, nennt man Funktionen höherer
+-- Ordnung. In funktionalen Programmiersprachen werden Funktionen als "first-class"
+-- behandelt. Man kann sie als Argument übergeben, als Rückgabewert einer Funktion
+-- zurückgeben oder einer Variable zuweisen.
+List.map double (List.range 1 4) -- [2, 4, 6, 8]
+
+-- Funktionen können auch als anonyme Funktion (Lambda-Funktionen) übergeben werden.
+-- Diese werden mit einem Blackslash eingeleitet, gefolgt von allen Argumenten.
+-- Die Funktion "\a -> a * 2" beschreibt die Funktion f(x) = x * 2.
+List.map (\a -> a * 2) (List.range 1 4) -- [2, 4, 6, 8]
+
+-- Mustervergleich kann auch in der Funktionsdefinition verwendet werden.
+-- In diesem Fall hat die Funktion ein Tupel als Parameter. (Beachte: Hier
+-- werden die Werte des Tupels direkt ausgepackt. Dadurch kann man auf die
+-- Verwendung von "first" und "second" verzichten.)
+area (width, height) =
+ width * height
+
+area (6, 7) -- 42
+
+-- Mustervergleich auf Records macht man mit geschweiften Klammern.
+-- Bezeichner (lokale Variablen) werden mittels dem "let" Keyword angelegt.
+-- (Mehr zu Records weiter unten!)
+volume {width, height, depth} =
+ let
+ area = width * height
+ in
+ area * depth
+
+volume { width = 3, height = 2, depth = 7 } -- 42
+
+-- Rekursive Funktion
+fib n =
+ if n < 2 then
+ 1
+ else
+ fib (n - 1) + fib (n - 2)
+
+List.map fib (List.range 0 8) -- [1, 1, 2, 3, 5, 8, 13, 21, 34]
+
+-- Noch eine rekursive Funktion (Nur ein Beispiel, verwende stattdessen immer
+-- List.length!)
+listLength aList =
+ case aList of
+ [] -> 0
+ x::xs -> 1 + listLength xs
+
+-- Funktionsapplikation hat die höchste Präzedenz, sie binden stärker als Operatoren.
+-- Klammern bietet die Möglichkeit der Bevorrangung.
+cos (degrees 30) ^ 2 + sin (degrees 30) ^ 2 -- 1
+-- Als erstes wird die Funktion "degrees" mit dem Wert 30 aufgerufen.
+-- Danach wird das Ergenis davon den Funktionen "cos", bzw. "sin" übergeben.
+-- Dann wird das Ergebnis davon mit 2 quadriert und als letztes werden diese
+-- beiden Werte dann addiert.
+
+{-- Typen und Typ Annotationen --}
+
+-- Durch Typinferenz kann der Compiler jeden Typ genau bestimmen. Man kann diese
+-- aber auch manuell selber angeben (guter Stil!).
+-- Typen beginnen immer mit eine Großbuchstaben. Dabei liest man "x : Typ" als
+-- "x" ist vom Typ "Typ".
+-- Hier ein paar übliche Typen:
+5 : Int
+6.7 : Float
+"hello" : String
+True : Bool
+
+-- Funktionen haben ebenfalls einen Typ. Dabei ist der ganz rechte Typ der
+-- Rückgabetyp der Funktion und alle anderen sind die Typen der Parameter.
+not : Bool -> Bool
+round : Float -> Int
+
+-- Es ist guter Stil immer den Typ anzugeben, da diese eine Form von Dokumentation
+-- sind. Außerdem kann so der Compiler genauere Fehlermeldungen geben.
+double : Int -> Int
+double x = x * 2
+
+-- Funktionen als Parameter werden durch Klammern angegeben. Die folgende Funktion
+-- ist nicht auf einen Typ festgelegt, sondern enthält Typvariablen (beginnend
+-- mit Kleinbuchstaben). Die konkreten Typen werden erst bei Anwendung der
+-- Funktion festgelegt. "List a" bedeutet, dass es sich um eine Liste mit
+-- Elementen vom Typ "a" handelt.
+List.map : (a -> b) -> List a -> List b
+
+-- Es gibt drei spezielle kleingeschriebene Typen: "number", "comparable" und
+-- "appendable".
+add : number -> number -> number
+add x y = x + y -- funktioniert mit Ints und Floats.
+
+max :: comparable -> comparable -> comparable
+max a b = if a > b then a else b -- funktioniert mit Typen, die vergleichbar sind.
+
+append :: appendable -> appendable -> appendable
+append xs ys = xs ++ ys -- funktioniert mit Typen, die konkatenierbar sind.
+
+append "hello" "world" -- "helloworld"
+append [1,1,2] [3,5,8] -- [1,1,2,3,5,8]
+
+{-- Eigene Datentypen erstellen --}
+
+-- Ein "Record" ist ähnlich wie ein Tupel, nur das jedes Feld einen Namne hat.
+-- Dabei spielt die Reihenfolge keine Rolle.
+{ x = 3, y = 7 }
+
+-- Um auf Werte eines Records zuzugreifen, benutzt man einen Punkt gefolgt
+-- von dem Namen des Feldes.
+{ x = 3, y = 7 }.x -- 3
+
+-- Oder mit einer Zugriffsfunktion, welche aus einem Punkt und dem Feldnamen besteht.
+.y { x = 3, y = 7 } -- 7
+
+-- Wert eines Feldes ändern. (Achtung: Das Feld muss aber vorher schon vorhanden sein!)
+{ person |
+ name = "George" }
+
+-- Mehrere Felder aufeinmal ändern unter Verwendung des alten Wertes.
+{ particle |
+ position = particle.position + particle.velocity,
+ velocity = particle.velocity + particle.acceleration }
+
+-- Du kannst ein Record auch als Typ Annotation verwenden.
+-- (Beachte: Ein Record Typ benutzt einen Doppelpunkt und ein Record Wert benutzt
+-- ein Gleichheitszeichen!)
+origin : { x : Float, y : Float, z : Float }
+origin =
+ { x = 0, y = 0, z = 0 }
+
+-- Durch das "type" Keyword kann man einem existierenden Typen einen Namen geben.
+type alias Point3D =
+ { x : Float, y : Float, z : Float }
+
+-- Der Name kann dann als Konstruktor verwendet werden.
+otherOrigin : Point3D
+otherOrigin =
+ Point3D 0 0 0
+
+-- Aber es ist immernoch der selbe Typ, da es nur ein Alias ist!
+origin == otherOrigin -- True
+
+-- Neben den Records gibt es auch noch so genannte Summentypen.
+-- Ein Summentyp hat mehrere Konstruktoren.
+type Direction =
+ North | South | East | West
+
+-- Ein Konstruktor kann außerdem noch andere Typen enthalten. Rekursion ist
+-- auch möglich.
+type IntTree =
+ Leaf | Node Int IntTree IntTree
+
+-- Diese können auch als Typ Annotation verwendet werden.
+root : IntTree
+root =
+ Node 7 Leaf Leaf
+
+-- Außerdem können auch Typvariablen verwendet werden in einem Konstruktor.
+type Tree a =
+ Leaf | Node a (Tree a) (Tree a)
+
+-- Beim Mustervergleich kann man auf die verschiedenen Konstruktoren matchen.
+leftmostElement : Tree a -> Maybe a
+leftmostElement tree =
+ case tree of
+ Leaf -> Nothing
+ Node x Leaf _ -> Just x
+ Node _ subtree _ -> leftmostElement subtree
+
+{-- Module und Imports --}
+
+-- Die Kernbibliotheken und andere Bibliotheken sind in Module aufgeteilt.
+-- Für große Projekte können auch eigene Module erstellt werden.
+
+-- Eine Modul beginnt mit ganz oben. Ohne diese Angabe befindet man sich
+-- automatisch im Modul "Main".
+module Name where
+
+-- Ohne genaue Angabe von Exports wird alles exportiert. Es können aber alle
+-- Exporte explizit angegeben werden.
+module Name (MyType, myValue) where
+
+-- Importiert das Modul "Dict". Jetzt kann man Funktionen mittels "Dict.insert"
+-- aufrufen.
+import Dict
+
+-- Importiert das "Dict" Modul und den "Dict" Typ. Dadurch muss man nicht "Dict.Dict"
+-- verwenden. Man kann trotzdem noch Funktionen des Moduls aufrufen, wie "Dict.insert".
+import Dict exposing (Dict)
+
+-- Abkürzung für den Modulnamen. Aufrufen der Funktionen mittels "C.funktionsName".
+import Graphics.Collage as C
+
+{-- Kommandozeilen Programme --}
+
+-- Eine Elm-Datei kompilieren.
+$ elm make MyFile.elm
+
+-- Beim ersten Aufruf wird Elm die "core" Bibliotheken installieren und eine
+-- "elm-package.json"-Datei anlegen, die alle Informationen des Projektes
+-- speichert.
+
+-- Der Reactor ist ein Server, welche alle Dateinen kompiliert und ausführt.
+$ elm reactor
+
+-- Starte das REPL (read-eval-print-loop).
+$ elm repl
+
+-- Bibliotheken werden durch den Github-Nutzernamen und ein Repository identifiziert.
+-- Installieren einer neuen Bibliothek.
+$ elm package install elm-lang/html
+-- Diese wird der elm-package.json Datei hinzugefügt.
+
+-- Zeigt alle Veränderungen zwischen zwei bestimmten Versionen an.
+$ elm package diff elm-lang/html 1.1.0 2.0.0
+-- Der Paketmanager von Elm erzwingt "semantic versioning"!
+```
+
+Elm ist eine besonders kleine Programmiersprache. Jetzt hast du genug Wissen an
+deiner Seite, um dich in fast jedem Elm Code zurecht zu finden.
+
+Noch ein paar weitere hilfreiche Ressourcen (in Englisch):
+
+- Die [Elm Homepage](http://elm-lang.org/). Dort findest du:
+
+ - [Anleitung zur Installierung von Elm](http://elm-lang.org/install)
+ - [Dokumentation](http://elm-lang.org/docs), sowie eine [Referenz zur Syntax](http://elm-lang.org/docs/syntax)
+ - Viele hilfreiche [Beispiele](http://elm-lang.org/examples)
+
+- Dokumentation der [Elm Kernbibliotheken](http://package.elm-lang.org/packages/elm-lang/core/latest/). Insbesondere:
+
+ - [Basics](http://package.elm-lang.org/packages/elm-lang/core/latest/Basics) (standardmäßig importiert)
+ - [Maybe](http://package.elm-lang.org/packages/elm-lang/core/latest/Maybe) sowie [Result](http://package.elm-lang.org/packages/elm-lang/core/latest/Result) (benutzt für Fehlerbehandlung)
+ - Datenstrukturen, wie [List](http://package.elm-lang.org/packages/elm-lang/core/latest/List), [Array](http://package.elm-lang.org/packages/elm-lang/core/latest/Array), [Dict](http://package.elm-lang.org/packages/elm-lang/core/latest/Dict), und [Set](http://package.elm-lang.org/packages/elm-lang/core/latest/Set)
+ - JSON [encoding](http://package.elm-lang.org/packages/elm-lang/core/latest/Json-Encode) und [decoding](http://package.elm-lang.org/packages/elm-lang/core/latest/Json-Decode)
+
+- [Die Elm Architektur](https://github.com/evancz/elm-architecture-tutorial#the-elm-architecture).
+
+- Die [Elm mailing list](https://groups.google.com/forum/#!forum/elm-discuss).
diff --git a/de-de/git-de.html.markdown b/de-de/git-de.html.markdown
index 61f7bb67..0896f513 100644
--- a/de-de/git-de.html.markdown
+++ b/de-de/git-de.html.markdown
@@ -10,7 +10,7 @@ lang: de-de
Git ist eine verteilte Versions- und Quellcodeverwaltung.
-Es nimmt Schnappschüsse der Projekte, um mit diesen Schnappschüssen verschiedene Versionen unterscheiden und den Quellcode verwalten zu können.
+Es nimmt Schnappschüsse der Projekte auf, um mit diesen Schnappschüssen verschiedene Versionen unterscheiden und den Quellcode verwalten zu können.
Anmerkung des Übersetzers: Einige englische Begriffe wie *Repository*, *Commit* oder *Head* sind idiomatische Bestandteile im Umgang mit Git. Sie wurden nicht übersetzt.
@@ -20,7 +20,7 @@ Anmerkung des Übersetzers: Einige englische Begriffe wie *Repository*, *Commit*
Eine Versionsverwaltung erfasst die Änderungen einer Datei oder eines Verzeichnisses im Verlauf der Zeit.
-### Zentrale im Vergleich mit verteilter Versionverwaltung
+### Vergleich zwischen Zentraler und verteilter Versionverwaltung
* 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.
@@ -43,13 +43,13 @@ Eine Versionsverwaltung erfasst die Änderungen einer Datei oder eines Verzeichn
### Repository (Repo)
-Ein Satz von Dateien, Verzeichnisen, Historieneinträgen, Commits und Heads. Stell es dir wie eine Quellcode-Datenstruktur vor, unter anderem mit der Eigenschaft, dass alle *Elemente* dir Zugriff auf die Revisionshistorie geben.
+Ein Satz von Dateien, Verzeichnissen, Historieneinträgen, Commits und Heads. Stell es dir wie eine Quellcode-Datenstruktur vor, unter anderem mit der Eigenschaft, dass alle *Elemente* dir Zugriff auf die Revisionshistorie geben.
Ein Repository besteht in Git aus dem .git-Verzeichnis und dem Arbeitsverzeichnis.
### .git-Verzeichnis (Teil des Repositorys)
-Das .git-Verzeichnis enthält alle Einstellung, Logs, Branches, den HEAD und mehr.
+Das .git-Verzeichnis enthält alle Einstellungen, Logs, Branches, den HEAD und mehr.
[Ausführliche Übersicht](http://gitready.com/advanced/2009/03/23/whats-inside-your-git-directory.html)
### Arbeitsverzeichnis (Teil des Repositorys)
@@ -66,7 +66,7 @@ Ein Commit ist ein Schnappschuss von Änderungen in deinem Arbeitsverzeichnis. W
### Branch
-Ein Branch, ein Ast oder Zweig, ist im Kern ein Pointer auf den letzten Commit, den du gemacht hast. Während des Commits wird der Pointer automatisch auf Stand gebracht und zeigt dann auf den neuen letzten Commit.
+Ein Branch, ein Ast oder Zweig, ist im Kern ein Pointer auf den letzten Commit, den du gemacht hast. Während des Commits wird der Pointer automatisch auf diesen Stand gebracht und zeigt dann auf den neuen letzten Commit.
### HEAD und head (Teil des .git-Verzeichnisses)
@@ -205,11 +205,17 @@ Speichert die aktuellen Inhalte des Index in einen neuen *Commit*. Dieser Commit
```bash
# Commit mit Beschreibung erstellen.
$ git commit -m "Added multiplyNumbers() function to HelloWorld.c"
+
+# Alle veränderten oder gelöschten Dateien außer neue Dateien werden gestaged und dann wird ein Commit erstellt.
+$ git commit -a -m "Modified foo.php and removed bar.php"
+
+# Ändert den letzten Commit (der letzte Commit wird mit einem neuen Commit ersetzt)
+$ git commit --amend -m "Correct message"
```
### diff
-Zeigt die Unterschiede zwischen Dateien von Arbeitsverzeichnisse, dem Index und Commits an.
+Zeigt die Unterschiede zwischen Dateien vom Arbeitsverzeichnis, dem Index und Commits an.
```bash
# Unterschiede zwischen deinem Arbeitsverzeichnis und dem Index anzeigen
@@ -324,7 +330,7 @@ $ git push origin master
### rebase (mit Vorsicht einsetzen)
-Nimm alle Änderungen, die in einem Branch durch Commits vorgenommen wurden, und übertrage sie auf einen anderen Branch. Achtung: Führe keinen Rebase von Commits durch, die auf ein öffentliches Repo gepusht wurden.
+Nimm alle Änderungen, die in einem Branch durch Commits vorgenommen wurden, und übertrage sie auf einen anderen Branch. Achtung: Führe keinen Rebase von Commits durch, die auf ein öffentliches Repo gepusht wurden!
```bash
# Rebase "experimentBranch" in den "master"-Branch
diff --git a/de-de/go-de.html.markdown b/de-de/go-de.html.markdown
index 817cb4ae..9409e181 100644
--- a/de-de/go-de.html.markdown
+++ b/de-de/go-de.html.markdown
@@ -94,7 +94,7 @@ Zeilenumbrüche beinhalten.` // Selber Zeichenketten-Typ
// Arrays haben bei Kompile-Zeit festgelegte Größen
var a4 [4]int // Ein Array mit 4 ints, alle mit Initialwert 0
- a3 := [...]int{3, 1, 5} // Ein Array mit 4 ints, Initialwerte wie angezeigt
+ a3 := [...]int{3, 1, 5} // Ein Array mit 3 ints, Initialwerte wie angezeigt
// "slices" haben eine dynamische Größe. Arrays und Slices haben beide ihre
// Vorzüge, aber slices werden viel häufiger verwendet
diff --git a/de-de/hq9+-de.html.markdown b/de-de/hq9+-de.html.markdown
new file mode 100644
index 00000000..841de5bb
--- /dev/null
+++ b/de-de/hq9+-de.html.markdown
@@ -0,0 +1,43 @@
+---
+language: HQ9+
+filename: hq9+-de.html
+contributors:
+ - ["Alexey Nazaroff", "https://github.com/rogaven"]
+translators:
+ - ["Dennis Keller", "https://github.com/denniskeller"]
+lang: de-de
+---
+
+HQ9+ ist eine Parodie auf esoterische Programmiersprachen und wurde von Cliff Biffle kreiert.
+Die Sprache hat nur vier Befehle und ist nicht Turing-vollständig.
+
+```
+Es gibt nur vier Befehle, die durch die folgenden vier Zeichen dargestellt werden
+H: druckt "Hello, world!"
+Q: druckt den Quellcode des Programms (ein Quine)
+9: druckt den Liedtext von "99 Bottles of Beer"
++: erhöhe den Akkumulator um Eins (Der Wert des Akkumulators kann nicht gelesen werden)
+Jedes andere Zeichen wird ignoriert.
+
+Ok. Lass uns ein Programm schreiben:
+ HQ
+
+Ergebnis:
+ Hello world!
+ HQ
+
+HQ9+ ist zwar sehr simpel, es erlaubt aber dir Sachen zu machen, die in
+anderen Sprachen sehr schwierig sind. Zum Beispiel druckt das folgende Programm
+drei Mal Kopien von sich selbst auf den Bildschirm:
+ QQQ
+Dies druckt:
+ QQQ
+ QQQ
+ QQQ
+```
+
+Und das ist alles. Es gibt sehr viele Interpreter für HQ9+.
+Unten findest du einen von ihnen.
+
++ [One of online interpreters](https://almnet.de/esolang/hq9plus.php)
++ [HQ9+ official website](http://cliffle.com/esoterica/hq9plus.html)
diff --git a/de-de/html-de.html.markdown b/de-de/html-de.html.markdown
index 2ee18129..8b5597e7 100644
--- a/de-de/html-de.html.markdown
+++ b/de-de/html-de.html.markdown
@@ -9,7 +9,7 @@ lang: de-de
---
HTML steht für HyperText Markup Language (Hypertext-Auszeichnungssprache).
-Sie ist eine Sprache, um Seiten für das World Wide Web zu schreiben..
+Sie ist eine Sprache, um Seiten für das World Wide Web zu schreiben.
Es ist eine Auszeichnugssprache, die es uns ermöglicht Webseiten mithilfe des Codes zu schreiben, der kennzeichnet wie Text und Daten angezeigt werden sollen. Eigentlich sind HTML Dateien nur einfache Textdateien.
Was sind das für Auszeichnungen? Es ist eine Methode, um die Daten der Website zu organisieren mithilfe von Start- und Endtags.
Diese Auszeichnung dient dazu dem Text Bedeutung zu geben, welchen sie umschließt.
@@ -50,10 +50,10 @@ Dieser Artikel ist bedacht darauf, nur HTML Syntax und nützliche Tipps zu geben
<!-- Danach startet sie mit einem Öffnungtag <html>. -->
<html>
-<!-- Dieser wird am Ende der Datei mit</html> geschlossen. -->
+<!-- Dieser wird am Ende der Datei mit </html> geschlossen. -->
</html>
-<!-- Nichts sollte nach diesen finalen Tag erscheinen. -->
+<!-- Nichts sollte nach diesem finalen Tag erscheinen. -->
<!-- Dazwischen (Zwischen dem Öffnungs- und Schließungstag <html></html>) finden wir: -->
@@ -65,13 +65,13 @@ Dieser Artikel ist bedacht darauf, nur HTML Syntax und nützliche Tipps zu geben
</head>
<!-- Nach dem <head> Bereich findet sich der <body> Tag -->
-<!-- Bis zu diesen Punkt wird nichts im Browerfenster angezeigt. -->
-<!-- Wir müssen den Body mit dem Inhalt füllen der angezeigt werden soll. -->
+<!-- Bis zu diesem Punkt wird nichts im Browerfenster angezeigt. -->
+<!-- Wir müssen den Body mit dem Inhalt füllen, der angezeigt werden soll. -->
<body>
<h1>Hallo, Welt!</h1> <!-- Der h1 Tag erstellt einen Titel. -->
<!-- Es gibt auch Untertitel für <h1> von den wichtigsten <h2> zu den Unwichtigsten (h6). -->
- <a href = "http://codepen.io/anon/pen/xwjLbZ">Komm, schaue was das zeigt</a> <!-- Eine URL wird zum Hyperlink, wenn es das Attribut href="" -->
+ <a href = "http://codepen.io/anon/pen/xwjLbZ">Komm, schaue was das zeigt</a> <!-- Eine URL wird zum Hyperlink, wenn es das Attribut href="" hat -->
<p>Das ist ein Absatz.</p> <!-- Der Tag <p> lässt uns Text auf die HTML Seite hinzufügen. -->
<p>Das ist ein anderer Absatz.</p>
<ul> <!-- Der <ul> Tag erstellt eine Aufzählungsliste. -->
@@ -93,12 +93,12 @@ Dieser Artikel ist bedacht darauf, nur HTML Syntax und nützliche Tipps zu geben
<!-- Es ist ebenso möglich eine Tabelle zu erstellen. -->
<table> <!-- Wir öffnen ein <table> Element. -->
- <tr> <!-- <tr> erlaubt es uns Reihe zu erstellen. -->
- <th>Erster Tabellenkopf</th> <!-- <th> erlaubt es uns der Tabelle einen Titel zu geben. -->
+ <tr> <!-- <tr> erlaubt es uns, Reihen zu erstellen. -->
+ <th>Erster Tabellenkopf</th> <!-- <th> erlaubt es uns, der Tabelle einen Titel zu geben. -->
<th>Zweiter Tabllenkopf</th>
</tr>
<tr>
- <td>Erste Zeile, erste Spalte</td> <!-- <td> erlaubt es eine Tabellenzelle zu erstellen. -->
+ <td>Erste Zeile, erste Spalte</td> <!-- <td> erlaubt es, eine Tabellenzelle zu erstellen. -->
<td>Erste Zeile, zweite Spalte</td>
</tr>
<tr>
@@ -111,7 +111,7 @@ Dieser Artikel ist bedacht darauf, nur HTML Syntax und nützliche Tipps zu geben
## Verwendung
-HTML Dateien enden mit `.html`.
+HTML Dateien enden mit `.html` oder mit `.htm`. Der Mime Typ ist meist `text/html`.
## Um mehr zu lernen
diff --git a/de-de/java-de.html.markdown b/de-de/java-de.html.markdown
index 001c6888..e52087ec 100644
--- a/de-de/java-de.html.markdown
+++ b/de-de/java-de.html.markdown
@@ -1,6 +1,6 @@
---
language: java
-filename: LearnJavaDe.java
+filename: LearnJavaDe-de.java
contributors:
- ["Jake Prather", "http://github.com/JakeHP"]
- ["Jakukyo Friel", "http://weakish.github.io"]
@@ -13,7 +13,7 @@ lang: de-de
Java ist eine Programmiersprache für vielfältige Aufgaben. Sie ist imperative und objektorientiert.
Oftmals wird sie für Desktop- Webapplikationen sowie als Programmiersprache im Betriebssystem Android verwendet.
-[Weitere Informationen \(Englisch\](http://docs.oracle.com/javase/tutorial/java/)
+[Weitere Informationen \(Englisch\)](http://docs.oracle.com/javase/tutorial/java/)
```java
// Einzeilige Kommentare starten mit //
@@ -477,7 +477,7 @@ Für tiefergreifende Fragen ist Google der beste Startpunkt.
* [Generics](http://docs.oracle.com/javase/tutorial/java/generics/index.html)
-* [Java Code Conventions](http://www.oracle.com/technetwork/java/codeconv-138413.html)
+* [Java Code Conventions](https://www.oracle.com/technetwork/java/codeconventions-150003.pdf)
**Online Tutorials**
diff --git a/de-de/javascript-de.html.markdown b/de-de/javascript-de.html.markdown
index f3917506..f817ee9f 100644
--- a/de-de/javascript-de.html.markdown
+++ b/de-de/javascript-de.html.markdown
@@ -1,7 +1,7 @@
---
language: javascript
contributors:
- - ["Adam Brenecki", "http://adam.brenecki.id.au"]
+ - ["Leigh Brenecki", "https://leigh.net.au"]
translators:
- ["ggb", "http://www.ideen-und-soehne.de"]
filename: learnjavascript-de.js
@@ -13,7 +13,7 @@ JavaScript wurde im Jahr 1995 von Brendan Eich bei Netscape entwickelt. Ursprün
Dabei ist JavaScript inzwischen nicht mehr auf Browser beschränkt: Node.js, ein Projekt, das eine eigene Laufzeitumgebung auf Grundlage von Google Chromes V8 mitbringt, wird derzeit immer populärer.
-Feedback ist herzlich Willkommen! Der ursprüngliche Autor ist unter [@adambrenecki](https://twitter.com/adambrenecki) oder [adam@brenecki.id.au](mailto:adam@brenecki.id.au) zu erreichen. Der Übersetzer unter [gregorbg@web.de](mailto:gregorbg@web.de).
+Feedback ist herzlich Willkommen! Der ursprüngliche Autor ist unter [@excitedleigh](https://twitter.com/excitedleigh) oder [l@leigh.net.au](mailto:l@leigh.net.au) zu erreichen. Der Übersetzer unter [gregorbg@web.de](mailto:gregorbg@web.de).
```js
// Kommentare werden wie in C gesetzt: Einzeilige Kommentare starten mit zwei
diff --git a/de-de/latex-de.html.markdown b/de-de/latex-de.html.markdown
index ee9c6e3e..8a952b15 100644
--- a/de-de/latex-de.html.markdown
+++ b/de-de/latex-de.html.markdown
@@ -39,13 +39,13 @@ filename: latex-de.tex
% Dieses Kommando kann man später benutzen.
\newcommand{\comment}[1]{}
-% Es können durchaus noch weitere Optione für das Dokument gesetzt werden!
+% Es können durchaus noch weitere Optionen für das Dokument gesetzt werden!
\author{Chaitanya Krishna Ande, Colton Kohnke \& Sricharan Chiruvolu}
\date{\today}
\title{Learn \LaTeX\ in Y Minutes!}
% Nun kann's losgehen mit unserem Dokument.
-% Alles vor dieser Zeile wird die Preamble genannt.
+% Alles vor dieser Zeile wird die Präambel genannt.
\begin{document}
\comment{
@@ -62,7 +62,7 @@ filename: latex-de.tex
% 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 -Dokumentation geschrieben in \LaTeX ! Wie ungewöhnlich und garantiert nicht meine Idee!
\end{abstract}
% Section Befehle sind intuitiv.
@@ -113,7 +113,7 @@ anderen Wissenschaften. Und deswegen müssen wir in der Lage sein, spezielle
Symbole zu unserem Paper hinzuzufügen! \\
Mathe kennt sehr viele Symbole, viel mehr als auf einer Tastatur zu finden sind;
-Symbole für Mengen und relationen, Pfeile, Operatoren und Griechische Buchstaben,
+Symbole für Mengen und Relationen, Pfeile, Operatoren und Griechische Buchstaben,
um nur ein paar zu nennen.\\
Mengen und Relationen spielen eine sehr wichtige Rolle in vielen mathematischen
diff --git a/de-de/make-de.html.markdown b/de-de/make-de.html.markdown
index 22c14a69..1bae332c 100644
--- a/de-de/make-de.html.markdown
+++ b/de-de/make-de.html.markdown
@@ -1,7 +1,9 @@
---
-language: make
+category: tool
+tool: make
contributors:
- ["Robert Steed", "https://github.com/robochat"]
+ - ["Stephan Fuhrmann", "https://github.com/sfuhrm"]
translators:
- ["Martin Schimandl", "https://github.com/Git-Jiro"]
filename: Makefile-de
@@ -9,14 +11,14 @@ 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
+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
+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.
+Es gibt eine Vielzahl an Varianten von Make, dieser Artikel beschäftigt sich
+mit der Version GNU Make. Diese Version ist Standard auf Linux.
```make
@@ -42,14 +44,15 @@ file0.txt:
# die erste Regel ist die Standard-Regel.
-# Diese Regel wird nur abgearbeitet wenn file0.txt aktueller als file1.txt ist.
+# 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.
+ # - bedeutet, dass Make die Abarbeitung fortsetzt auch wenn Fehler
+ # passieren.
# Versuche `make file1.txt` auf der Kommandozeile.
# Eine Regel kann mehrere Ziele und mehrere Voraussetzungen haben.
@@ -57,16 +60,16 @@ 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
+# 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
+# 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.
@@ -87,14 +90,14 @@ ex0.txt ex1.txt: maker
# Automatische Variablen & Wildcards
#-----------------------------------------------------------------------
-process: file*.txt # Eine Wildcard um Dateinamen zu Vergleichen
+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 $? # Nur die Voraussetzungen, die nicht aktuell sind.
@echo $+ # Alle Voraussetzungen inklusive Duplikate (nicht wie Üblich)
#@echo $| # Alle 'order only' Voraussetzungen
@@ -112,20 +115,20 @@ process: ex1.txt file0.txt
%.png: %.svg
inkscape --export-png $^
-# Muster-Vergleichs-Regeln werden nur abgearbeitet wenn make entscheidet das Ziel zu
-# erzeugen
+# 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
+# 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
+# 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
@@ -169,7 +172,7 @@ name4 ?= Jean
# nicht gibt.
override name5 = David
-# Verhindert das Kommando-Zeilen Argumente diese Variable ändern können.
+# Verhindert, dass Kommando-Zeilen Argumente diese Variable ändern können.
name4 +=grey
# Werte an eine Variable anhängen (inkludiert Leerzeichen).
@@ -177,14 +180,14 @@ name4 +=grey
# 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!)
+ # kann, wenn es zu kompilizert wird!)
-# Ein paar Variablen die von Make automatisch definiert werden.
+# Ein paar Variablen, die von Make automatisch definiert werden.
echo_inbuilt:
echo $(CC)
- echo ${CXX)}
+ echo ${CXX}
echo $(FC)
- echo ${CFLAGS)}
+ echo ${CFLAGS}
echo $(CPPFLAGS)
echo ${CXXFLAGS}
echo $(LDFLAGS)
@@ -194,7 +197,7 @@ echo_inbuilt:
# Variablen 2
#-----------------------------------------------------------------------
-# Der erste Typ von Variablen wird bei jeder verwendung ausgewertet.
+# 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)
@@ -213,7 +216,7 @@ var4 ::= good night
# Funktionen
#-----------------------------------------------------------------------
-# Make verfügt über eine vielzahl von Funktionen.
+# Make verfügt über eine Vielzahl von Funktionen.
sourcefiles = $(wildcard *.c */*.c)
objectfiles = $(patsubst %.c,%.o,$(sourcefiles))
diff --git a/de-de/markdown-de.html.markdown b/de-de/markdown-de.html.markdown
index 2c838660..729e883c 100644
--- a/de-de/markdown-de.html.markdown
+++ b/de-de/markdown-de.html.markdown
@@ -14,7 +14,7 @@ Syntax, in der sich Dokumente leicht schreiben *und* lesen lassen. Außerdem
sollte Markdown sich leicht nach HTML (und in andere Formate) konvertieren
lassen.
-```markdown
+```md
<!-- Markdown ist eine Obermenge von HTML - jede valide HTML-Datei ist also
automatisch valides Markdown - was heisst dass wir jedes HTML-Element (also auch
Kommentare) in Markdown benutzen können, ohne dass der Parser sie verändert.
@@ -144,7 +144,7 @@ indem du eine Zeile mit vier Leerzeichen oder einem Tabulator einrückst -->
puts item
end
-<!-- Innerhalb normalen Texts kannst du Code mit Backticks ` auszeichnen -->
+<!-- Innerhalb normalen Texts kannst du Code mit Backticks \` auszeichnen -->
Hermann hatte nicht die leiseste Ahnung, was dieses `go_to()` bedeuten könnte!
@@ -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).
diff --git a/de-de/nix-de.html.markdown b/de-de/nix-de.html.markdown
new file mode 100644
index 00000000..ea02e81d
--- /dev/null
+++ b/de-de/nix-de.html.markdown
@@ -0,0 +1,358 @@
+---
+language: nix
+filename: learnnix-de.nix
+contributors:
+ - ["Chris Martin", "http://chris-martin.org/"]
+translators:
+ - ["Dennis Keller", "https://github.com/denniskeller"]
+lang: de-de
+---
+
+Nix ist eine simple funktionale Programmiersprache, die für den
+[Nix package manager](https://nixos.org/nix/) und
+[NixOS](https://nixos.org/) entwickelt wurde.
+
+Du kannst Nix Ausdrücke evaluieren mithilfe von
+[nix-instantiate](https://nixos.org/nix/manual/#sec-nix-instantiate)
+oder [`nix-repl`](https://github.com/edolstra/nix-repl).
+
+```
+with builtins; [
+
+ # Kommentare
+ #=========================================
+
+ # Inline Kommentare sehen so aus.
+
+ /* Multizeilen Kommentare
+ sehen so aus. */
+
+
+ # Booleans
+ #=========================================
+
+ (true && false) # Und
+ #=> false
+
+ (true || false) # Oder
+ #=> true
+
+ (if 3 < 4 then "a" else "b") # Bedingungen
+ #=> "a"
+
+
+ # Integers
+ #=========================================
+
+ # Integers sind die einzigen numerischen Typen.
+
+ 1 0 42 (-3) # Einige integers
+
+ (4 + 6 + 12 - 2) # Addition
+ #=> 20
+
+ (7 / 2) # Division
+ #=> 3
+
+
+ # Strings
+ #=========================================
+
+ "String Literale sind in Anführungszeichen."
+
+ "
+ String Literale können mehrere
+ Zeilen umspannen.
+ "
+
+ ''
+ Dies wird als Literal mit eingerückten String bezeichnet.
+ Es entfernt intelligent führende Leerzeichen.
+ ''
+
+ ''
+ a
+ b
+ ''
+ #=> "a\n b"
+
+ ("ab" + "cd") # String Konkatenation
+ #=> "abcd"
+
+ # Mit Antiquotation kannst du Werte in Strings einbetten.
+ ("Dein Homeverzeichnis ist ${getEnv "HOME"}")
+ #=> "Dein Homeverzeichnis ist /home/alice"
+
+
+ # Paths
+ #=========================================
+
+ # Nix besitzt einen primitiven Datentyp für Pfade
+ /tmp/tutorials/learn.nix
+
+ # Ein relativer Pfad wird beim Parsing zu einem absoluten Pfad aufgelöst,
+ # relativ zu der Datei in der es auftritt.
+ tutorials/learn.nix
+ #=> /the-base-path/tutorials/learn.nix
+
+ # Ein Pfad muss mindestens einen Schrägstrich enthalten. Ein Pfad für eine
+ # Datei im selben Verzeichnis benötigt ein ./ Präfix.
+ ./learn.nix
+ #=> /the-base-path/learn.nix
+
+ # Der / Operator muss von Leerraum umgeben sein wenn du dividieren möchtest.
+ 7/2 # Das ist ein Pfadliteral
+ (7 / 2) # Das ist ein Integerliteral
+
+
+ # Importe
+ #=========================================
+
+ # Eine nix Datei besitzt einen einzelnen top-level Ausdruck mit keinen freien Variablen.
+ # Ein Import-Ausdruck wird zum Wert der Datei, die importiert wird, ausgewertet.
+ (import /tmp/foo.nix)
+
+ # Importe können ebenso mit Strings spezifiziert werden.
+ (import "/tmp/foo.nix")
+
+ # Import Pfade müssen absolut sein. Pfadliterale
+ # sind automatisch aufgelöst, das ist ein Ordnung.
+ (import ./foo.nix)
+
+ # Jedoch passiert dies nicht mit Strings.
+ (import "./foo.nix")
+ #=> error: string ‘foo.nix’ doesn't represent an absolute path
+
+
+ # Let
+ #=========================================
+
+ # `let` Blöcke erlauben es uns Werte zu Variablen zu binden.
+ (let x = "a"; in
+ x + x + x)
+ #=> "aaa"
+
+ # Bindungen können auf sich gegenseitig verweisen. Die Reihenfolge spielt
+ # keine Rolle.
+ (let y = x + "b";
+ x = "a"; in
+ y + "c")
+ #=> "abc"
+
+ # Innere Bindungen überschatten Äußere.
+ (let a = 1; in
+ let a = 2; in
+ a)
+ #=> 2
+
+
+ # Funktionen
+ #=========================================
+
+ (n: n + 1) # Funktion, die 1 addiert
+
+ ((n: n + 1) 5) # Dieselbe Funktion angewendet auf 5.
+ #=> 6
+
+ # Es gibt keine spezielle Syntax für benannte Funktionen, aber sie
+ # können mit `let` Blöcken, wie jeder andere Wert auch, gebunden werden.
+ (let succ = (n: n + 1); in succ 5)
+ #=> 6
+
+ # Eine Funktion hat genau ein Argument.
+ # Mehrere Argumente können erreicht werden mithilfe von Currying.
+ ((x: y: x + "-" + y) "a" "b")
+ #=> "a-b"
+
+ # Benannte Funktionsargumente gibt es auch. Diese werden wir einführen, nachdem wir uns Sets
+ # angeschaut haben.
+
+ # Listen
+ #=========================================
+
+ # Listen werden durch eckige Klammern gekennzeichnet.
+
+ (length [1 2 3 "x"])
+ #=> 4
+
+ ([1 2 3] ++ [4 5])
+ #=> [1 2 3 4 5]
+
+ (concatLists [[1 2] [3 4] [5]])
+ #=> [1 2 3 4 5]
+
+ (head [1 2 3])
+ #=> 1
+ (tail [1 2 3])
+ #=> [2 3]
+
+ (elemAt ["a" "b" "c" "d"] 2)
+ #=> "c"
+
+ (elem 2 [1 2 3])
+ #=> true
+ (elem 5 [1 2 3])
+ #=> false
+
+ (filter (n: n < 3) [1 2 3 4])
+ #=> [ 1 2 ]
+
+
+ # Sets
+ #=========================================
+
+ # Ein "Set" ist eine ungeordnete Zuordnung mit Stringschlüsseln.
+ { foo = [1 2]; bar = "x"; }
+
+ # Der . Operator nimmt einen Wert aus dem Set.
+ { a = 1; b = 2; }.a
+ #=> 1
+
+ # Der ? Operator testet, ob der Schlüssel in dem Set vorhanden ist.
+ ({ a = 1; b = 2; } ? a)
+ #=> true
+ ({ a = 1; b = 2; } ? c)
+ #=> false
+
+ # Der // Operator mergt zwei Sets.
+ ({ a = 1; } // { b = 2; })
+ #=> { a = 1; b = 2; }
+
+ # Werte auf der rechten Seite überschreiben die Werte auf der linken Seite.
+ ({ a = 1; b = 2; } // { a = 3; c = 4; })
+ #=> { a = 3; b = 2; c = 4; }
+
+ # Das Schlüsselwort rec bezeichenet ein "rekursives Set", in dem sich Attribute
+ # aufeinander beziehen können.
+ (let a = 1; in { a = 2; b = a; }.b)
+ #=> 1
+ (let a = 1; in rec { a = 2; b = a; }.b)
+ #=> 2
+
+ # Verschachtelte Sets können stückweise definiert werden.
+ {
+ a.b = 1;
+ a.c.d = 2;
+ a.c.e = 3;
+ }.a.c
+ #=> { d = 2; e = 3; }
+
+ # Die Nachkommen eines Attributs können in diesem Feld nicht zugeordnet werden, wenn
+ # das Attribut selbst nicht zugewiesen wurde.
+ {
+ a = { b = 1; };
+ a.c = 2;
+ }
+ #=> error: attribute ‘a’ already defined
+
+
+ # With
+ #=========================================
+
+ # Der Körper eines Sets Blocks wird mit der Zuordnung eines Satzes an die Variablen gebunden.
+ (with { a = 1; b = 2; };
+ a + b)
+ # => 3
+
+ # Innere Bindungen überschatten äußere Bindungen.
+ (with { a = 1; b = 2; };
+ (with { a = 5; };
+ a + b))
+ #=> 7
+
+ # Die erste Linie diese Tutorials startet mit "with builtins;",
+ # weil builtins ein Set mit allen eingebauten
+ # Funktionen (length, head, tail, filter, etc.) umfasst.
+ # Das erspart uns beispielsweise "builtins.length" zu schreiben,
+ # anstatt nur "length".
+
+
+ # Set patterns
+ #=========================================
+
+ # Sets sind nützlich, wenn du mehrere Werte einer Funktion
+ # übergeben musst.
+ (args: args.x + "-" + args.y) { x = "a"; y = "b"; }
+ #=> "a-b"
+
+ # Dies kann mit Hilfe von Set patterns deutlicher geschrieben werden.
+ ({x, y}: x + "-" + y) { x = "a"; y = "b"; }
+ #=> "a-b"
+
+ # Standardmäßig schlägt das Muster bei Sets mit zusätzlichen Schlüsseln fehl.
+ ({x, y}: x + "-" + y) { x = "a"; y = "b"; z = "c"; }
+ #=> error: anonymous function called with unexpected argument ‘z’
+
+ # Durch Hinzufügen von ", ..." können zusätzliche Schlüssel ignoriert werden.
+ ({x, y, ...}: x + "-" + y) { x = "a"; y = "b"; z = "c"; }
+ #=> "a-b"
+
+
+ # Errors
+ #=========================================
+
+ # `throw` bewirkt, dass die Auswertung mit einer Fehlermeldung abgebrochen wird.
+ (2 + (throw "foo"))
+ #=> error: foo
+
+ # `tryEval` fängt geworfene Fehler.
+ (tryEval 42)
+ #=> { success = true; value = 42; }
+ (tryEval (2 + (throw "foo")))
+ #=> { success = false; value = false; }
+
+ # `abort` ist ähnlich wie throw, aber es ist fatal. Es kann nicht gefangen werden.
+ (tryEval (abort "foo"))
+ #=> error: evaluation aborted with the following error message: ‘foo’
+
+ # `assert` evaluiert zu dem gegebenen Wert, wenn die Bedingung wahr ist, sonst
+ # löst es eine abfangbare Exception aus.
+ (assert 1 < 2; 42)
+ #=> 42
+ (assert 1 > 2; 42)
+ #=> error: assertion failed at (string):1:1
+ (tryEval (assert 1 > 2; 42))
+ #=> { success = false; value = false; }
+
+
+ # Impurity
+ #=========================================
+
+ # Da die Wiederholbarkeit von Builds für den Nix Packetmanager entscheidend ist,
+ # werden in der Nix Sprache reine funktionale Elemente betont. Es gibt aber ein paar
+ # unreine Elemente.
+ # Du kannst auf Umgebungsvariablen verweisen.
+ (getEnv "HOME")
+ #=> "/home/alice"
+
+ # Die trace Funktion wird zum Debugging verwendet. Sie gibt das erste Argument zu stderr aus
+ # und evaluiert das zweite Argument.
+ (trace 1 2)
+ #=> trace: 1
+ #=> 2
+
+ # Du kannst Dateien in den Nix Store schreiben. Obwohl unrein, kannst du dir relativ sicher sein,
+ # dass es sicher ist, da der Dateiname aus dem Hash des Inhalts abgeleitet wird.
+ # Du kannst Dateien von überall lesen. In diesem Beispiel schreiben wir Dateien in den Store
+ # und lesen wieder davon.
+ (let filename = toFile "foo.txt" "hello!"; in
+ [filename (builtins.readFile filename)])
+ #=> [ "/nix/store/ayh05aay2anx135prqp0cy34h891247x-foo.txt" "hello!" ]
+
+ # Außerdem können wir Dateien in den Nix Store herunterladen.
+ (fetchurl "https://example.com/package-1.2.3.tgz")
+ #=> "/nix/store/2drvlh8r57f19s9il42zg89rdr33m2rm-package-1.2.3.tgz"
+
+]
+```
+
+### Weitere Ressourcen
+
+* [Nix Manual - Nix expression language]
+ (https://nixos.org/nix/manual/#ch-expression-language)
+
+* [James Fisher - Nix by example - Part 1: The Nix expression language]
+ (https://medium.com/@MrJamesFisher/nix-by-example-a0063a1a4c55)
+
+* [Susan Potter - Nix Cookbook - Nix By Example]
+ (https://ops.functionalalgebra.com/nix-by-example/)
diff --git a/de-de/opencv-de.html.markdown b/de-de/opencv-de.html.markdown
new file mode 100644
index 00000000..223e6cd8
--- /dev/null
+++ b/de-de/opencv-de.html.markdown
@@ -0,0 +1,153 @@
+---
+category: tool
+tool: OpenCV
+filename: learnopencv-de.py
+contributors:
+ - ["Yogesh Ojha", "http://github.com/yogeshojha"]
+translators:
+ - ["Dennis Keller", "https://github.com/denniskeller"]
+lang: de-de
+---
+### Opencv
+
+OpenCV (Open Source Computer Vision) ist eine Bibliothek von Programmierfunktionen,
+die hauptsächlich auf maschinelles Sehen in Echtzeit ausgerichtet ist.
+Ursprünglich wurde OpenCV von Intel entwickelt. Später wurde es von von
+Willow Garage und dann Itseez (das später von Intel übernommen wurde) unterstützt.
+OpenCV unterstützt derzeit eine Vielzahl von Sprachen, wie C++, Python, Java uvm.
+
+#### Installation
+
+Bitte lese diese Artikel für die Installation von OpenCV auf deinen Computer.
+
+* Windows Installationsanleitung: [https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_setup/py_setup_in_windows/py_setup_in_windows.html#install-opencv-python-in-windows]()
+* Mac Installationsanleitung (High Sierra): [https://medium.com/@nuwanprabhath/installing-opencv-in-macos-high-sierra-for-python-3-89c79f0a246a]()
+* Linux Installationsanleitung (Ubuntu 18.04): [https://www.pyimagesearch.com/2018/05/28/ubuntu-18-04-how-to-install-opencv]()
+
+### Hier werden wir uns auf die Pythonimplementierung von OpenCV konzentrieren.
+
+```python
+# Bild in OpenCV lesen
+import cv2
+img = cv2.imread('Katze.jpg')
+
+# Bild darstellen
+# Die imshow() Funktion wird verwendet um das Display darzustellen.
+cv2.imshow('Image',img)
+# Das erste Argument ist der Titel des Fensters und der zweite Parameter ist das Bild
+# Wenn du den Fehler Object Type None bekommst ist eventuell dein Bildpfad falsch.
+# Bitte überprüfe dann den Pfad des Bildes erneut.
+cv2.waitKey(0)
+# waitKey() ist eine Tastaturbindungsfunktion, sie nimmt Argumente in
+# Millisekunden an. Für GUI Ereignisse MUSST du die waitKey() Funktion verwenden.
+
+# Ein Bild schreiben
+cv2.imwrite('graueKatze.png',img)
+# Das erste Arkument ist der Dateiname und das Zweite ist das Bild
+
+# Konveriere das Bild zu Graustufen
+gray_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
+
+# Videoaufnahme von der Webcam
+cap = cv2.VideoCapture(0)
+# 0 ist deine Kamera, wenn du mehrere Kameras hast musst du deren Id eingeben
+while(True):
+ # Erfassen von Einzelbildern
+ _, frame = cap.read()
+ cv2.imshow('Frame',frame)
+ # Wenn der Benutzer q drückt -> beenden
+ if cv2.waitKey(1) & 0xFF == ord('q'):
+ break
+# Die Kamera muss wieder freigegeben werden
+cap.release()
+
+# Wiedergabe von Videos aus einer Datei
+cap = cv2.VideoCapture('film.mp4')
+while(cap.isOpened()):
+ _, frame = cap.read()
+ # Das Video in Graustufen abspielen
+ gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
+ cv2.imshow('frame',gray)
+ if cv2.waitKey(1) & 0xFF == ord('q'):
+ break
+cap.release()
+
+# Zeichne eine Linie in OpenCV
+# cv2.line(img,(x,y),(x1,y1),(color->r,g,b->0 to 255),thickness)
+cv2.line(img,(0,0),(511,511),(255,0,0),5)
+
+# Zeichne ein Rechteck
+# cv2.rectangle(img,(x,y),(x1,y1),(color->r,g,b->0 to 255),thickness)
+# thickness = -1 wird zum Füllen des Rechtecks verwendet
+cv2.rectangle(img,(384,0),(510,128),(0,255,0),3)
+
+# Zeichne ein Kreis
+cv2.circle(img,(xCenter,yCenter), radius, (color->r,g,b->0 to 255), thickness)
+cv2.circle(img,(200,90), 100, (0,0,255), -1)
+
+# Zeichne eine Ellipse
+cv2.ellipse(img,(256,256),(100,50),0,0,180,255,-1)
+
+# Text auf Bildern hinzufügen
+cv2.putText(img,"Hello World!!!", (x,y), cv2.FONT_HERSHEY_SIMPLEX, 2, 255)
+
+# Bilder zusammenfüggen
+img1 = cv2.imread('Katze.png')
+img2 = cv2.imread('openCV.jpg')
+dst = cv2.addWeighted(img1,0.5,img2,0.5,0)
+
+# Schwellwertbild
+# Binäre Schwellenwerte
+_,thresImg = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
+# Anpassbare Schwellenwerte
+adapThres = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY,11,2)
+
+# Weichzeichnung von einem Bild
+# Gausßscher Weichzeichner
+blur = cv2.GaussianBlur(img,(5,5),0)
+# Rangordnungsfilter
+medianBlur = cv2.medianBlur(img,5)
+
+# Canny-Algorithmus
+img = cv2.imread('Katze.jpg',0)
+edges = cv2.Canny(img,100,200)
+
+# Gesichtserkennung mit Haarkaskaden
+# Lade die Haarkaskaden von https://github.com/opencv/opencv/blob/master/data/haarcascades/ herunter
+import cv2
+import numpy as np
+face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
+eye_cascade = cv2.CascadeClassifier('haarcascade_eye.xml')
+
+img = cv2.imread('Mensch.jpg')
+gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
+
+aces = face_cascade.detectMultiScale(gray, 1.3, 5)
+for (x,y,w,h) in faces:
+ cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
+ roi_gray = gray[y:y+h, x:x+w]
+ roi_color = img[y:y+h, x:x+w]
+ eyes = eye_cascade.detectMultiScale(roi_gray)
+ for (ex,ey,ew,eh) in eyes:
+ cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(0,255,0),2)
+
+cv2.imshow('img',img)
+cv2.waitKey(0)
+
+cv2.destroyAllWindows()
+# destroyAllWindows() zerstört alle Fenster
+# Wenn du ein bestimmtes Fenter zerstören möchtest musst du den genauen Namen des
+# von dir erstellten Fensters übergeben.
+```
+
+### Weiterführende Literatur:
+* Lade Kaskade hier herunter [https://github.com/opencv/opencv/blob/master/data/haarcascades]()
+* OpenCV Zeichenfunktionen [https://docs.opencv.org/2.4/modules/core/doc/drawing_functions.html]()
+* Eine aktuelle Sprachenreferenz kann hier gefunden werden [https://opencv.org]()
+* Zusätzliche Ressourcen können hier gefunden werden [https://en.wikipedia.org/wiki/OpenCV]()
+* Gute OpenCV Tutorials
+ * [https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_tutorials.html]()
+ * [https://realpython.com/python-opencv-color-spaces]()
+ * [https://pyimagesearch.com]()
+ * [https://www.learnopencv.com]()
+ * [https://docs.opencv.org/master/]()
diff --git a/de-de/paren-de.html.markdown b/de-de/paren-de.html.markdown
new file mode 100644
index 00000000..641e226e
--- /dev/null
+++ b/de-de/paren-de.html.markdown
@@ -0,0 +1,200 @@
+---
+
+language: Paren
+filename: learnparen-de.paren
+contributors:
+ - ["KIM Taegyoon", "https://github.com/kimtg"]
+ - ["Claudson Martins", "https://github.com/claudsonm"]
+translators:
+ - ["Dennis Keller", "https://github.com/denniskeller"]
+lang: de-de
+---
+
+[Paren](https://bitbucket.org/ktg/paren) ist ein Dialekt von Lisp.
+Es ist als eingebettete Sprache konzipiert.
+
+Manche Beispiele sind von <http://learnxinyminutes.com/docs/racket/>.
+
+```scheme
+;;; Kommentare
+# Kommentare
+
+;; Einzeilige Kommentare starten mit einem Semikolon oder einem Hashtag
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 1. Primitive Datentypen und Operatoren
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; Zahlen
+123 ; int
+3.14 ; double
+6.02e+23 ; double
+(int 3.14) ; => 3 : int
+(double 123) ; => 123 : double
+
+;; Funktionsapplikationen werden so geschrieben: (f x y z ...)
+;; Dabei ist f eine Funktion und x, y, z sind die Operatoren.
+;; Wenn du eine Literalliste von Daten erstelllen möchtest,
+;; verwende (quote) um zu verhindern, dass sie ausgewertet zu werden.
+(quote (+ 1 2)) ; => (+ 1 2)
+;; Nun einige arithmetische Operationen
+(+ 1 1) ; => 2
+(- 8 1) ; => 7
+(* 10 2) ; => 20
+(^ 2 3) ; => 8
+(/ 5 2) ; => 2
+(% 5 2) ; => 1
+(/ 5.0 2) ; => 2.5
+
+;;; Wahrheitswerte
+true ; for Wahr
+false ; for Falsch
+(! true) ; => Falsch
+(&& true false (prn "doesn't get here")) ; => Falsch
+(|| false true (prn "doesn't get here")) ; => Wahr
+
+;;; Zeichen sind Ints.
+(char-at "A" 0) ; => 65
+(chr 65) ; => "A"
+
+;;; Zeichenketten sind ein Array von Zahlen mit fester Länge.
+"Hello, world!"
+"Benjamin \"Bugsy\" Siegel" ; Backslash ist ein Escape-Zeichen
+"Foo\tbar\r\n" ; beinhaltet C Escapes: \t \r \n
+
+;; Zeichenketten können auch verbunden werden!
+(strcat "Hello " "world!") ; => "Hello world!"
+
+;; Eine Zeichenketten kann als Liste von Zeichen behandelt werden
+(char-at "Apple" 0) ; => 65
+
+;; Drucken ist ziemlich einfach
+(pr "Ich bin" "Paren. ") (prn "Schön dich zu treffen!")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 2. Variablen
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Du kannst Variablen setzen indem du (set) verwedest
+;; eine Variable kann alle Zeichen besitzen außer: ();#"
+(set some-var 5) ; => 5
+some-var ; => 5
+
+;; Zugriff auf eine zuvor nicht zugewiesene Variable erzeugt eine Ausnahme
+; x ; => Unknown variable: x : nil
+
+;; Lokale Bindung: Verwende das Lambda Calculus! 'a' und 'b'
+;; sind nur zu '1' und '2' innerhalb von (fn ...) gebunden.
+((fn (a b) (+ a b)) 1 2) ; => 3
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 3. Sammlungen
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; Listen
+
+;; Listen sind Vektrorartige Datenstrukturen. (Zufälliger Zugriff ist O(1).
+(cons 1 (cons 2 (cons 3 (list)))) ; => (1 2 3)
+;; 'list' ist ein komfortabler variadischer Konstruktor für Listen
+(list 1 2 3) ; => (1 2 3)
+;; und ein quote kann als literaler Listwert verwendet werden
+(quote (+ 1 2)) ; => (+ 1 2)
+
+;; Du kannst 'cons' verwenden um ein Element an den Anfang einer Liste hinzuzufügen.
+(cons 0 (list 1 2 3)) ; => (0 1 2 3)
+
+;; Listen sind ein sehr einfacher Typ, daher gibt es eine Vielzahl an Funktionen
+;; für Sie. Ein paar Beispiele:
+(map inc (list 1 2 3)) ; => (2 3 4)
+(filter (fn (x) (== 0 (% x 2))) (list 1 2 3 4)) ; => (2 4)
+(length (list 1 2 3 4)) ; => 4
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 3. Funktionen
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Verwende 'fn' um Funktionen zu erstellen.
+;; eine Funktion gibt immer den Wert ihres letzten Ausdrucks zurück
+(fn () "Hello World") ; => (fn () Hello World) : fn
+
+;; Verwende Klammern um alle Funktionen aufzurufen, inklusive Lambda Ausdrücke
+((fn () "Hello World")) ; => "Hello World"
+
+;; Zuweisung einer Funktion zu einer Variablen
+(set hello-world (fn () "Hello World"))
+(hello-world) ; => "Hello World"
+
+;; Du kannst dies mit syntaktischen Zucker für die Funktionsdefinition verkürzen:
+(defn hello-world2 () "Hello World")
+
+;; Die () von oben ist eine Liste von Argumente für die Funktion.
+(set hello
+ (fn (name)
+ (strcat "Hello " name)))
+(hello "Steve") ; => "Hello Steve"
+
+;; ... oder gleichwertig, unter Verwendung mit syntaktischen Zucker:
+(defn hello2 (name)
+ (strcat "Hello " name))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 4. Gleichheit
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Für Zahlen verwende '=='
+(== 3 3.0) ; => wahr
+(== 2 1) ; => falsch
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 5. Kontrollfluss
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; Bedingungen
+
+(if true ; test Ausdruck
+ "this is true" ; then Ausdruck
+ "this is false") ; else Ausdruck
+; => "this is true"
+
+;;; Schleifen
+
+;; for Schleifen ist für Zahlen
+;; (for SYMBOL START ENDE SCHRITT AUSDRUCK ..)
+(for i 0 10 2 (pr i "")) ; => schreibt 0 2 4 6 8 10
+(for i 0.0 10 2.5 (pr i "")) ; => schreibt 0 2.5 5 7.5 10
+
+;; while Schleife
+((fn (i)
+ (while (< i 10)
+ (pr i)
+ (++ i))) 0) ; => schreibt 0123456789
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 6. Mutation
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Verwende 'set' um einer Variablen oder einer Stelle einen neuen Wert zuzuweisen.
+(set n 5) ; => 5
+(set n (inc n)) ; => 6
+n ; => 6
+(set a (list 1 2)) ; => (1 2)
+(set (nth 0 a) 3) ; => 3
+a ; => (3 2)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 7. Makros
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Makros erlauben es dir die Syntax der Sprache zu erweitern.
+;; Parens Makros sind einfach.
+;; Tatsächlich ist (defn) ein Makro.
+(defmacro setfn (name ...) (set name (fn ...)))
+(defmacro defn (name ...) (def name (fn ...)))
+
+;; Lass uns eine Infix Notation hinzufügen
+;; Let's add an infix notation
+(defmacro infix (a op ...) (op a ...))
+(infix 1 + 2 (infix 3 * 4)) ; => 15
+
+;; Makros sind nicht hygenisch, Du kannst bestehende Variablen überschreiben!
+;; Sie sind Codetransformationenen.
+```
diff --git a/de-de/perl-de.html.markdown b/de-de/perl-de.html.markdown
index fd8fb3c4..13c00b01 100644
--- a/de-de/perl-de.html.markdown
+++ b/de-de/perl-de.html.markdown
@@ -8,9 +8,9 @@ translators:
lang: de-de
---
-Perl 5 ist eine sehr mächtige, funktionsreiche Programmiersprache mit über 25 Jahren Entwicklungsgeschichte.
+Perl ist eine sehr mächtige, funktionsreiche Programmiersprache mit über 25 Jahren Entwicklungsgeschichte.
-Perl 5 läuft auf über 100 Platformen von portablen Geräten bis hin zu Mainframes. Perl 5 ist geeignet für Rapid-Prototyping und auch groß angelegte Entwicklungs-Projekte.
+Perl läuft auf über 100 Platformen von portablen Geräten bis hin zu Mainframes. Perl ist geeignet für Rapid-Prototyping und auch groß angelegte Entwicklungs-Projekte.
```perl
# Einzeilige Kommentare beginnen mit dem # Symbol.
diff --git a/de-de/processing-de.html.markdown b/de-de/processing-de.html.markdown
new file mode 100644
index 00000000..42ae2233
--- /dev/null
+++ b/de-de/processing-de.html.markdown
@@ -0,0 +1,498 @@
+---
+language: processing
+filename: learnprocessing.pde
+contributors:
+ - ["Phone Thant Ko", "http://github.com/phonethantko"]
+ - ["Divay Prakash", "https://github.com/divayprakash"]
+translators:
+ - ["caminsha", "https://github.com/caminsha"]
+filename: processing-de.md
+lang: de-de
+---
+
+## Einführung
+
+Processing ist eine Programmiersprache, welche es ermöglicht, digitale Kunst
+und multimediale Inhalte zu erstellen. Mit Processing können Personen ohne
+Programmiererfahrung die Grundlagen der Computerprogrammierung in einem
+visuellen Kontext erlernen.
+
+Obwohl Processing von Java beeinflusst wurde und auf Java basiert, ist die Syntax
+sowohl von Java als auch Javascript beeinflusst worden. Weitere Informationen
+sind [hier](https://processing.org/reference/) zu finden.
+
+Die Programmiersprache wird statisch programmiert und kommt mit einer eigenen
+offiziellen IDE, damit die Programme kompiliert und ausgeführt werden können.
+
+```
+/* ------------
+ Mehrzeilige Kommentare werden so gemacht
+*/
+
+// Einzeilige Kommentare funktionieren so //
+
+/*
+ Da Processing von Java abstammt, ist die Syntax für Kommentare gleich
+ wie bei Java (wie du vielleicht oben bemerkt hast)!
+ Mehrzeilige Kommentare werden wie hier umschloßen.
+*/
+
+/* -------------------------------------------------
+ Schreiben und Ausführen von Processing Programmen
+ -------------------------------------------------
+*/
+
+// In Processing ist der Startpunkt eines Programms die Funktion `setup()`
+// mit dem Rückgabetyp `void`.
+// Beachte: Die Syntax ist derjenigen von C++ ziemlich ähnlich.
+void setup() {
+ // Dies gibt beim Ausführen "Hallo Welt!" auf der Konsole aus.
+ println("Hallo Welt!"); // eine weitere Sprache mit einem Semikolon am Ende.
+}
+
+// Normalerweise wird der Code für statische Elemente innerhalb der Methode
+// `setup()` geschrieben, da diese lediglich einmal ausgeführt wird.
+// Dies kann zum Beispiel das Setzen der Hintergrundfarbe oder das Bestimmen
+// der Canvas-Größe sein.
+background(color); // Setze die Hintergrundfarbe
+size(width, height, [renderer]); // bestimme die Canvasgröße mit dem optionalen
+ // Parameter `renderer`.
+// Du wirst innerhalb dieses Dokuments noch weitere Parameter sehen.
+
+// Wenn du möchstest, dass Code unendlich oft ausgeführt wird, so muss dieser
+// Code innerhalb der `draw()`-Methode stehen.
+// `draw()` muss existieren, wenn du möchtest, dass das Programm durchgehend
+// läuft. Die `draw()`-Methode darf nur einmal vorkommen.
+
+int i = 0;
+void draw() {
+ // Dieser Codeblock wird ausgeführt bis er gestoppt wird.
+ print(i);
+ i++; // Inkrement-Operator
+}
+
+// Da wir nun wissen, wie man ein funktionierendes Skript erstellen kann und wie
+// dieses ausgeführt wird, fahren wir mit den unterschiedlichen Datentypen und
+// Collections weiter, welche in Processing unterstützt werden.
+
+/* -------------------------------------------------
+ Datentypen und Collections
+ -------------------------------------------------
+*/
+
+// Gemäß den Angaben in der Processingreferenz, unterstützt Processing die
+// folgenden acht primitiven Datentypen:
+boolean booleanValue = true; // Boolean
+byte byteValueOfA = 23; // Byte
+char charValueOfA = 'A'; // Char (einzelnes Zeichen)
+color colorValueOfWhiteM = color(255, 255, 255); // Farben (angegeben durch die
+ // `color()`-Methode)
+color colorValueOfWhiteH = #FFFFFF; // Farbe (angegeben mit der Hexadezimal-
+ // schreibweise.)
+int intValue = 5; // Integer (ganze Zahl)
+long longValue = 2147483648L; // "L" wird hinzugefügt, um es als `long` zu
+ // markieren.
+float floatValue = 1.12345; // Float (32-Bit Gleitkommazahl)
+double doubleValue = 1.12345D // Double (64-Bit Gleitkommazahl)
+
+//BEACHTE!
+// Auch wenn es die Datentypen "long" und "double" gibt und auch funktionieren,
+// verwenden Processing-Funktionen diese Datentypen nicht. Das bedeutet, dass
+// diese zu "int" resp. "float" konvertiert werden müssen.
+// Dies geschieht, indem man `(int)` oder `(float)` vor die Variable schreibt,
+// bevor diese einer Funktion übergeben werden.
+
+// Es gibt eine ganze Reiher zusammengesetzter Datentypen, welche in Processing
+// gebraucht werden können. Um Zeit zu sparen, gehen wir in diesem Tutorial
+// lediglich die wichtigsten durch.
+
+// String
+// Während der Datentyp `char` einfache Anzührungszeichen (' ') braucht, haben
+// Strings doppelte Anführungszeichen (" ").
+String sampleString = "Hallo, Processing!";
+// Strings können auch durch ein Array von `char`s erstellt werden.
+// Wir werden Arrays gleich anschauen.
+char source = {'H', 'A', 'L', 'L', 'O'};
+String stringFromSource = new String(source); // HALLO
+// Wie auch in Java können in Processing Strings auch zusammengefügt werden
+// mit dem +-Operator.
+print("Hallo " + "Welt!"); // => Hallo Welt!
+
+
+// Arrays
+// In Processing können Arrays jeden Datentypen beinhalten, sogar Objekte.
+// Da Arrays ähnlich wie Objekte sind, müssen diese mit dem Schlüsselwort `new`
+// erstellt werden.
+int[] intArray = new int[5];
+int[] intArrayWithValues = {1, 2, 3} // Arrays können auch mit Daten gefüllt
+ // werden.
+// ArrayList
+// Die Funktionen einer ArrayList sind ähnlich wie die eines Arrays und können
+// auch jegliche Datentypen beinhalten. Der einzige Unterschied zwischen Arrays
+// und `ArrayList`s ist, dass eine `ArrayList` die Größe dynamisch anpassen kann,
+// da es eine Implementierung des "List" Interface in Java ist.
+ArrayList<Integer> intArrayList = new ArrayList<Integer>();
+
+// Objekte
+// Da Processing auf Java basiert, unterstützt Processing die Objektorientierte
+// Programmierung. Dies bedeutet, dass du grundsätzlich jegliche Datentypen
+// selber erstellen kannst und diese nach deinen Bedürfnissen manipulieren kannst.
+// Selbstverständlich muss eine Klasse definiert werden bevor du ein Objekt
+// davon instanzieren kannst.
+// Format: ClassName InstanceName
+SomeRandomClass myObject // hier musst du das Objekt später instazieren
+// Hier wird das Objekt direkt instanziert:
+SomeRandomClass myObjectInstantiated = new SomeRandomClass();
+
+// Processing hat noch weitere Collections (wie zum Beispiel Dictionaries und
+// Listen). Aus Einfachheitsgründen wird dies in diesem Tutorial weggelassen.
+
+/* -------------------------------------------------
+ Mathematik
+ -------------------------------------------------
+*/
+
+// Arithmetik
+1 + 1 // => 2
+2 -1 // => 1
+2 * 3 // => 6
+3 / 2 // => 1
+3.0 / 2 // => 1.5
+3.0 % 2 // => 1.0 (Modulo)
+
+// Processing beinhaltet auch einige Funktionen, welche mathematische
+// Operationen vereinfachen
+float f = sq(3); // Quadrat => f = 9.0
+float p = pow(3, 3); // Potenz => p = 27.0
+int a = abs(-13); // Absolute Zahl => a = 13
+int r1 = round(3.1); // Runden => r1 = 3
+int r2 = round(3.7); // Runden => r2 = 4
+int sr = sqrt(25); // Quadratwurzel => sr = 5.0
+
+// Vektoren
+// Processing bietet eine einfache Möglichkeit an, mit Vektoren zu arbeiten mit
+// der Klasse PVector. Die Klasse kann zwei- und dreidimensionale Vektoren
+// darstellen und bietet Methoden an, welche nützlich sein können für Matrizen-
+// Operationen. Weitere Informationen findest du hier:
+// (https://processing.org/reference/PVector.html)
+
+// Trigonometrie
+// Processing unterstützt auch trigonometrische Operationen mit Hilfe dieser
+// Funktionen: `sin()`, `cos()`, `tan()`, `asin()`, `atan()`. Für die einfache
+// Konvertierung gibt es außerdem noch die Funktionen `degrees()` und `radians()`.
+// Die trigonometrischen Funktionen rechnen mit dem Winkelmaß Radian, wodurch
+// die Gradzahlen zuerst konvertiert werden müssen.
+float one = sin(PI/2); // => one = 1.0
+// Wie du vielleicht bemerkt hast, existieren einige Konstanten für trigo-
+// metrische Operationen; `PI`, `HALF_PI`, `QUARTER_PI` und so weiter ...
+
+/* -------------------------------------------------
+ Kontrollstrukturen
+ -------------------------------------------------
+*/
+
+// Bedingte Anweisungen
+// Bedinge Anweisungen werden gleich wie in Java geschrieben.
+if (author.getAppearence().equals("hot")) {
+ print("Narzissmus vom Feinsten!")
+} else {
+ // Du kannst hier weitere Bedingungen prüfen.
+ print("Irgendetwas ist falsch hier!");
+}
+// Für die `if`-Anweisungen gibt es auch eine Kurzschreibweise
+// Dies sind sogenannte ternäre Operatoren.
+int i = 3;
+String value = (i > 5) ? "Groß" : "Klein"; // => "Klein"
+
+// Die Switch-Case-Anweisung kann verwendet werden, um mehrere Bedingungen
+// zu prüfen.
+// Wichtig ist, dass nach jeder Bedingung ein `break`-Statement verwendet wird,
+// sonst werden alle folgenden ausgeführt und es wird nicht mehr überprüft, ob
+// die Bedingung wahr ist.
+int value = 2;
+switch(value) {
+ case 0:
+ print("Auf keinen Fall!"); // Dies wird nicht ausgeführt.
+ break; // Geht zum nächsten Statement und prüft dieses
+ case 1:
+ print("Wir kommen näher..."); // Auch dies wird nicht ausgeführt
+ break;
+ case 2:
+ print("Bravo!"); // Dies wird ausgeführt.
+ break;
+ default:
+ print("Nicht gefunden."); // Diese Zeile wird ausgeführt, wenn keine
+ // der anderen Operatoren wahr sind.
+ break;
+}
+
+// Wiederholungen
+// For-Schleifen - Auch hier ist die Syntax wieder gleich wie in Java
+for(int i = 0; i < 5; i++) {
+ print(i); // Gibt die Zahlen 0 bis 4 aus.
+}
+
+// While-Statements
+int j = 3;
+while(j > 0) {
+ print(j);
+ j--; // Dies ist wichtig, dass der Code nicht unendlich lange läuft.
+}
+
+// `loop()` | `noloop()` | `redraw()` | `exit()`
+// Dies sind spezifische Funktionen, welche in Processing verwendet werden
+// können, um den Programmablauf zu steuern.
+loop(); // erlaubt es der `draw()`-Methode immer zu laufen, während
+noloop(); // dies nur für einmal erlaubt.
+redraw(); // führt die `draw()`-Methode noch einmal aus.
+exit(); // Diese Methode stoppt das Programm. Dies kann nützlich sein, wenn die
+ // Methode `draw()` immer läuft.
+```
+
+## Mit Processing zeichnen
+
+Da du nun die Grundsätze der Programmiersprache verstanden hast, schauen wir
+uns nun das Beste an Processing an - Das Zeichnen!
+
+```
+
+/* -------------------------------------------------
+ Figuren
+ -------------------------------------------------
+*/
+
+// 2D-Figuren
+
+// Punkte
+point(x,y); // im zweidimensionalen Raum
+point(x, y, z); // im dreidimensionalen Raum
+// Diese Befehle zeichnen einen Punkt an der Koordinate.
+
+// Linien
+line(x1, y1, x2, y2); // im zweidimensionalen Raum
+// Dies zeichnet eine Linie, welche durch die zwei Punkte (x1, y1) und (x2, y2)
+// definiert wird.
+line(x1, y1, z1, x2, y2, z2); // im dreidimensionalen Raum
+// Analog wird hier eine Linie gezeichnet mit drei Punkten
+
+// Dreieck
+triangle(x1, y1, x2, y2, x3, y3);
+// Zeichnet ein Dreieck, welches als Eckpunkte die drei Koordinaten hat.
+
+// Rechteck
+rect(a, b, c, d, [r]); // Mit dem optionalen Parameter kann der Winkel aller
+ // vier Ecken definiert werden
+rect(a, b, c, d, [tl, tr, br, bl]); // Mit weiteren optionalen Parametern kann
+ // jeder Winkel des Rechtecks definiert werden.
+// Dies zeichnet ein Quadrat mit der Koordinate {a, b} als linke obere Ecke
+// die Parameter c und d sind für die Breite und Höhe.
+
+// Vierecke
+quad(x, y, x2, y2, x3, y3, x4, y4);
+// Dies zeichnet ein Viereck, welches die einzelnen Koordinaten als Eckpunkte hat.
+
+// Ellipse
+ellipse(x, y, width, height);
+// Zeichnet eine Ellipse beim Punkt {x. y}. Die Breite und die Höhe werden durch
+// die Parameter width und height definiert.
+
+// Arc
+arc(x, y, width, height, start, stop, [mode]);
+// Die ersten vier Parameter sollten selbsterklärend sein.
+// start und end definieren die Winkel, bei welchen `arc` starten resp. enden
+// (in Radians)
+// Der optionale Parameter `mode` definiert, ob der Kreisbogen gefüllt wird
+// oder nicht.
+// Die möglichen Optionen für `mode` sind: PIE, CHORD und OPEN.
+
+// Kurven
+// Processing bietet zwei mögliche Kurven an, welche verwendet werden können.
+// Da es hier darum geht, dass es möglichst simpel ist, werden hier keine
+// weiteren Details genannt. Wenn du Kurven in deinem Programm verwenden möchtest,
+// sind die folgenden Links empfehlenswert:
+// https://processing.org/reference/curve_.html
+// https://processing.org/reference/bezier_.html
+
+
+// 3D-Figuren
+
+// Der dreidimensionale Raum kann aktiviert werden, indem man den Renderer-
+// Parameter in der Methode `size()` zu "P3D" setzt.
+size(width, height, P3D);
+// Im dreidimensionalen Raum müssen die Koordinaten übersetzt werden, damit
+// diese korrekt gerendert werden.
+
+// Box
+box(size); // Würfel mit der Seitenlänge `size`
+box(w, h, d); // Quader definiert durch Breite, Höhe und Tiefe
+
+// Kugel
+sphere(radius); // Die Größe wird definiert durch den Parameter `radius`
+// Der Mechanismus hinter dem Rendern von Kugeln wurde durch mosaikartige
+// Dreiecke implementiert.
+// Mit der folgenden Funktion ist es möglich, zu bestimmen wie detailliert die
+// Kugel gerendert wird.
+// spereDetail(res);
+// Weitere Informationen sind hier zu finden: (https://processing.org/reference/sphereDetail_.html)
+
+// Unregelmäßige Figuren
+// Was ist, wenn du etwas zeichnen möchtest, was nicht durch Processing-Funktionen
+// abgedeckt ist?
+// Es ist möglich, die Funktionen `beginShape()`, `endShape()` und `vertex(x,y)
+// zu verwenden.
+// Weitere Informationen findest du hier: (https://processing.org/reference/beginShape_.html)
+// Du kannst selber gemachte Formen auch verwenden mit der PShape-Klasse.
+// Informationen zu PShape gibt es hier: (https://processing.org/reference/PShape.html)
+
+/* -------------------------------------------------
+ Transformationen
+ -------------------------------------------------
+*/
+
+// Tranformationen sind nützlich, um ständig zu wissen, wo die Koordinaten und
+// die Ecken einer Form sind, welche du gezeichnet hast. Grundsätzlich sind dies
+// Matrizenoperationen. `pushMatrix()`, `popMatrix()` und `translate()`.
+pushMatrix(); // Speichert das aktuelle Koordinatensystem auf dem Stack
+ // alle Transformationen werden hier angewendet.
+popMatrix(); // Stellt das gespeicherte Koordinatensystem wieder her.
+// Wenn du diese Funktionen verwendest, kann das Koordinatensystem gespeichert
+// und visualisiert werden, ohne dass es Konflikte gibt.
+
+// Translate
+translate(x,y); // Setzt den Ursprung zu diesem Punkt.
+translate(x, y, z); // Pendant zu der oberen Funktion im dreidimensionalen Raum
+
+// Rotationen
+rotate(angle); // Rotiere, um den Betrag, welcher spezifiert wurde.
+// Es gibt drei Pendants im dreidimensionalen Raum.
+// Namentlich sind dies: `rotateX(angle)`, `rotateY(angle)` und `rotateZ(angle)`
+
+// Skalierung
+scale(s); // Skaliert das Koordinatensystem (entweder erweitern oder verkleinern)
+
+/* -------------------------------------------------
+ Styling und Texturen
+ -------------------------------------------------
+*/
+
+// Farben
+// Wie ich zuvor schon erklärt habe, kann die Hintergrundfarbe mit der Funktion
+// `background()` definiert werden. Außerdem ist es möglich, dass man zuerst
+// eine Farbe definiert und diese erst danach der Funktion übergeben wird.
+color c = color(255, 255, 255); // WEISS!
+// Standardmäßig verwendet Processing das RGB-Farbschema, aber dies kann
+// zu HSB konfiguriert werden, indem die Funktion `colorMode()` verwendet wird.
+// Weitere Informationen findest du hier: (https://processing.org/reference/colorMode_.html)
+background(c); // Ab jetzt ist der Hintergrund in weiß.
+// Du kannst die Funktion `fill()` verwenden, um die Farbe auszuwählen, mit
+// welcher die Formen ausgefüllt werden.
+// Dies muss konfiguriert werden bevor Formen und Figuren gezeichnet werden.
+fill(color(0, 0, 0));
+// Wenn du nur die Farbe der Umrandungen definieren möchtest, kannst du die
+// Funktion `stroke()` verwenden.
+stroke(255, 255, 0, 200); // Linienfarbe wird zu gelb mit einer höheren
+ // Transparenz geändert.
+
+// Bilder
+// Processing kann Bilder rendern und diese unterschiedlich verwenden. Die
+// meisten Bilder sind im Datentyp `PImage` gespeichert.
+filter(shader); // Processing unterstützt mehrere Filter-Funktionen, damit
+ // Bilder verändert werden können.
+texture(image); // PImage kann als Argument, weiteren Funktionen übergeben
+ // werden, um die Figuren zu "Text" zu machen.
+```
+
+Wenn du weitere Dinge mit Processing kennenlernen willst, dann gibt es unzählige
+Dinge, welche du mit Processing machen kannst. Das Rendern von Modellen,
+Schattierungen und viele mehr. Für ein kurzes Tutorial bietet Processing zu viel,
+daher verweise ich dich, falls du interessiert bist, auf die offizielle
+Dokumentaion.
+
+```
+// Bevor wir weiterfahren, werde ich einige Aspekte zum Importieren von
+// Bibliotheken und Paketen sagen, damit du Processing erweitern kannst..
+
+/* -------------------------------------------------
+ Import
+ -------------------------------------------------
+*/
+
+// Die Macht von Processing kann besser veranschaulicht werden, wenn wir
+// Bibliotheken und Pakete importieren.
+// Die Import-Anweisung kann wie unten geschrieben zu Beginn des Quelltextes
+// geschrieben werden.
+import processing.something.*;
+```
+
+## Beispielprogramm
+
+Lass uns ein Beispiel von openprocessing.org ansehen, welches verdeutlicht,
+was man in Processing mit nur wenigen Zeilen Code machen kann.
+
+Kopiere den nachfolgenden Code in deine Processing IDE.
+
+```
+// Disclaimer: Ich habe das Porgramm nicht selbst geschriben. Diese Skizze
+// stammt aus openprocessing, allerdings soll dieses Programm zeigen, wie wenig
+// Zeilen Code notwendig sind, um etwas Cooles zu machen.
+// Abgerufen von: (https://www.openprocessing.org/sketch/559769)
+
+float theta;
+float a;
+float col;
+float num;
+
+void setup() {
+ size(600,600);
+}
+
+void draw() {
+ background(#F2F2F2);
+ translate(width/2, height/2);
+ theta = map(sin(millis()/1000.0), -1, 1, 0, PI/6);
+
+ float num=6;
+ for (int i=0; i<num; i++) {
+ a =350;
+ rotate(TWO_PI/num);
+ branch(a);
+ }
+}
+
+void branch(float len) {
+ col=map(len, 0, 90, 150, 255);
+ fill(col, 0, 74);
+ stroke (col, 0, 74);
+ line(0, 0, 0, -len);
+ ellipse(0, -len, 3, 3);
+ len*=0.7;
+
+ if (len>30) {
+ pushMatrix();
+ translate(0, -30);
+ rotate(theta);
+ branch(len);
+ popMatrix();
+
+ pushMatrix();
+ translate(0, -30);
+ rotate(-theta);
+ branch(len);
+ popMatrix();
+ }
+}
+```
+
+Processing ist einfach zu erlernen und ist vorallem nützlich, um Multimedia-
+Inhalte (auch in 3D) zu erstellen ohne viel Code zu schreiben. Es ist so einfach
+gehalten, dass man den Code durchlesen kann und man versteht den Programmablauf
+bereits.
+
+Wenn du externe Bibliotheken, Pakete oder eigene Klassen einbindest, kann ein
+Programm, welches mit Processing geschrieben wurde, durchaus auch kompliziert
+werden.
+
+## Einige nützliche Links
+
+- [Processing Webseite](http://processing.org)
+- [Processing Sketches](http://openprocessing.org)
diff --git a/de-de/pug-de.html.markdown b/de-de/pug-de.html.markdown
new file mode 100644
index 00000000..c86494ce
--- /dev/null
+++ b/de-de/pug-de.html.markdown
@@ -0,0 +1,208 @@
+---
+language: Pug
+contributors:
+ - ["Michael Warner", "https://github.com/MichaelJGW"]
+filename: lernepug-de.pug
+translators:
+ - ["denniskeller", "https://github.com/denniskeller"]
+lang: de-de
+---
+
+## Erste Schritte mit Pug
+
+Pug ist eine kleine Sprache, die zu HTML kompiliert. Sie hat eine
+saubere Syntax mit zusätzlichen Funktionen wie if Anweisungen und Schleifen.
+Sie kann auch als serverseitige Templatingsprache für Serversprachen
+wie NodeJS verwendet werden.
+
+### Die Sprache
+```pug
+
+//- Einzeilenkommentar
+
+//- Mehrzeiliger
+ Kommentar
+
+//- ---TAGS---
+//- Grundlagen
+div
+//- <div></div>
+h1
+//- <h1></h1>
+mein-benutzerdefiniertesTag
+//- <mein-benutzerdefiniertesTag></mein-benutzerdefiniertesTag>
+
+//- Geschwister
+div
+div
+//- <div></div>
+ <div></div>
+
+//- Kind
+div
+ div
+//- <div>
+ <div></div>
+ </div>
+
+//- Text
+h1 Hallo Welt
+//- <h1>Hallo Welt</h1>
+
+//- Multizeilentext
+div.
+ Hallo
+ Welt
+//- <div>
+ Hallo
+ Welt
+ </div>
+
+//- ---ATTRIBUTE---
+div(class="meine-klasse" id="meine-id" mein-benutzerdefiniertes-attr="data" enabled)
+//- <div class="meine-klasse" id="meine-id" mein-benutzerdefiniertes-attr="data" enabled></div>
+
+//- Kurzhand
+span.meine-klasse
+//- <span class="meine-klasse"></span>
+.meine-klasse
+//- <div class="meine-klasse"></div>
+div#meine-id
+//- <div id="meine-id"></div>
+div#meine-id.meine-klasse
+//- <div class="meine-klasse" id="meine-id"></div>
+
+
+//- ---JS---
+- const sprache = "pug";
+
+//- Multizeilen JS
+-
+ const srache = "pug";
+ const cool = true;
+
+//- JS Klassen
+- const meineKlasse = ['class1', 'class2', 'class3']
+div(class=meineKlasse)
+//- <div class="class1 class2 class3"></div>
+
+//- JS Stil
+- const meineStile = {'color':'white', 'background-color':'blue'}
+div(styles=meineStile)
+//- <div styles="{&quot;color&quot;:&quot;white&quot;,&quot;background-color&quot;:&quot;blue&quot;}"></div>
+
+//- JS Attributte
+- const meineAttribute = {"src": "foto.png", "alt": "meine Bilder"}
+img&attributes(meineAttribute)
+//- <img src="foto.png" alt="meine Bilder">
+- let deaktiviert = false
+input(type="text" disabled=deaktiviert)
+//- <input type="text">
+- deaktiviert = true
+input(type="text" disabled=deaktiviert)
+//- <input type="text" disabled>
+
+//- JS Templating
+- const name = "Bob";
+h1 Hi #{name}
+h1= name
+//- <h1>Hi Bob</h1>
+//- <h1>Bob</h1>
+
+//- ---Schleifen---
+
+//- 'each' und 'for' machen das Selbe. Wir werden nur 'each' verwenden.
+
+each value, i in [1,2,3]
+ p=value
+//-
+ <p>1</p>
+ <p>2</p>
+ <p>3</p>
+
+each value, index in [1,2,3]
+ p=value + '-' + index
+//-
+ <p>1-0</p>
+ <p>2-1</p>
+ <p>3-2</p>
+
+each value in []
+ p=value
+//-
+
+each value in []
+ p=value
+else
+ p Keine Werte sind hier
+
+//- <p>Keine Werte sind hier</p>
+
+//- ---BEDINGUNGEN---
+
+- const zahl = 5
+if zahl < 5
+ p zahl ist kleiner als 5
+else if zahl > 5
+ p zahl ist größer als 5
+else
+ p zahl ist 5
+//- <p>zahl ist 5</p>
+
+- const bestellungsStatus = "Ausstehend";
+case bestellungsStatus
+ when "Ausstehend"
+ p.warn Deine Bestellung steht noch aus
+ when "Abgeschlossen"
+ p.success Bestellung ist abgeschlossen.
+ when -1
+ p.error Ein Fehler ist aufgetreten
+ default
+ p kein Bestellprotokoll gefunden
+//- <p class="warn">Deine Bestellung steht noch aus</p>
+
+//- --INCLUDE--
+//- File path -> "includes/nav.png"
+h1 Firmenname
+nav
+ a(href="index.html") Home
+ a(href="about.html") Über uns
+
+//- Dateipfad -> "index.png"
+html
+ body
+ include includes/nav.pug
+//-
+ <html>
+ <body>
+ <h1>Firmenname</h1>
+ <nav><a href="index.html">Home</a><a href="about.html">Über uns</a></nav>
+ </body>
+ </html>
+
+//- Importiere JS und CSS
+script
+ include scripts/index.js
+style
+ include styles/theme.css
+
+//- ---MIXIN---
+mixin basic()
+ div Hallo
++basic("Bob")
+//- <div>Hallo</div>
+
+mixin comment(name, kommentar)
+ div
+ span.comment-name= name
+ div.comment-text= kommentar
++comment("Bob", "Das ist super")
+//- <div>Hallo</div>
+
+```
+
+
+### Zusätzliche Ressourcen
+- [The Site](https://pugjs.org/)
+- [The Docs](https://pugjs.org/api/getting-started.html)
+- [Github Repo](https://github.com/pugjs/pug)
diff --git a/de-de/pyqt-de.html.markdown b/de-de/pyqt-de.html.markdown
new file mode 100644
index 00000000..93ee20d4
--- /dev/null
+++ b/de-de/pyqt-de.html.markdown
@@ -0,0 +1,89 @@
+---
+category: tool
+tool: PyQT
+filename: learnpyqt-de.py
+contributors:
+ - ["Nathan Hughes", "https://github.com/sirsharpest"]
+translators:
+ - ["Dennis Keller", "https://github.com/denniskeller"]
+lang: de-de
+---
+
+**Qt** ist eine weit bekanntes Framework mit den man plattformunabhängige Programme schreiben kann,
+die auf verschiedenen Sotfware und Hardware Plattformen laufen mit kleinen oder keinen Änderungen im Code.
+Dabei besitzen sie trozdem die Power und Geschwindigkeit von nativen Anwendungen.
+**Qt** wurde ursprünglich in *C++** geschrieben.
+
+Das ist eine Adaption von dem C++ Intro für QT von [Aleksey Kholovchuk](https://github.com/vortexxx192),
+manche der Codebeispiele sollte in der selben Funktionalität resultieren.
+Diese Version wurde in pyqt erstellt.
+
+```python
+import sys
+from PyQt4 import QtGui
+
+def window():
+ # Erschafft ein Anwendungsobjekt.
+ app = QtGui.QApplication(sys.argv)
+ # Erschafft ein Widget, auf dem unser Label platziert wird.
+ w = QtGui.QWidget()
+ # Fügt ein Label zu dem Widget hinzu.
+ b = QtGui.QLabel(w)
+ # Setzt einen Text für das Label.
+ b.setText("Hello World!")
+ # Setzt die Größe und die Platzierungsinfomationen.
+ w.setGeometry(100, 100, 200, 50)
+ b.move(50, 20)
+ # Setzt unserem Fenster einen schönen Titel.
+ w.setWindowTitle("PyQt")
+ # Lässt alles anzeigen.
+ w.show()
+ # Führe alles aus, nachdem wir alles aufgebaut haben.
+ sys.exit(app.exec_())
+
+if __name__ == '__main__':
+ window()
+
+```
+
+Damit wir weitere fortgeschrittene Funktionen in **pyqt** verwenden können,
+müssen wir anfangen zusätzliche Elemente zu bauen.
+Hier zeigen wir wie man eine Dialog Popup Box einführt.
+Diese ist nützlich, um den Benutzer eine Entscheidung zu bestätigen oder um Informationen anzuzeigen.
+
+```Python
+import sys
+from PyQt4.QtGui import *
+from PyQt4.QtCore import *
+
+
+def window():
+ app = QApplication(sys.argv)
+ w = QWidget()
+ # Erschafft einen Knopf und fügt das Widget w hinzu
+ b = QPushButton(w)
+ b.setText("drücke mich")
+ b.move(50, 50)
+ # Wenn b gedrückt wird, wird diese Funktion aufgerufen.
+ # Bemerke das Fehlen von () bei dem Funktionsaufruf.
+ b.clicked.connect(showdialog)
+ w.setWindowTitle("PyQt Dialog")
+ w.show()
+ sys.exit(app.exec_())
+
+# Diese Funktion soll ein Dialogfenster mit einem Knopf erschaffen.
+# Der Knopf wartet bis er geklickt wird und beendet das Programm
+def showdialog():
+ d = QDialog()
+ b1 = QPushButton("ok", d)
+ b1.move(50, 50)
+ d.setWindowTitle("Dialog")
+ # Diese Modalität sagt dem Popup, dass es den Parent blocken soll, solange es aktiv ist.
+ d.setWindowModality(Qt.ApplicationModal)
+ # Beim klicken möchte ich, dass der gesamte Prozess beendet wird.
+ b1.clicked.connect(sys.exit)
+ d.exec_()
+
+if __name__ == '__main__':
+ window()
+```
diff --git a/de-de/python-de.html.markdown b/de-de/python-de.html.markdown
index ae29d6f9..337f1224 100644
--- a/de-de/python-de.html.markdown
+++ b/de-de/python-de.html.markdown
@@ -1,9 +1,10 @@
---
-language: python
+language: Python
contributors:
- ["Louie Dinh", "http://ldinh.ca"]
translators:
- ["kultprok", "http:/www.kulturproktologie.de"]
+ - ["matthiaskern", "https://github.com/matthiaskern"]
filename: learnpython-de.py
lang: de-de
---
@@ -11,13 +12,16 @@ lang: de-de
Anmerkungen des ursprünglichen Autors:
Python wurde in den frühen Neunzigern von Guido van Rossum entworfen. Es ist heute eine der beliebtesten Sprachen. Ich habe mich in Python wegen seiner syntaktischen Übersichtlichkeit verliebt. Eigentlich ist es ausführbarer Pseudocode.
-Feedback ist herzlich willkommen! Ihr erreicht mich unter [@louiedinh](http://twitter.com/louiedinh) oder louiedinh [at] [google's email service]
+Feedback ist herzlich willkommen! Ihr erreicht mich unter [@louiedinh](http://twitter.com/louiedinh) oder louiedinh [at] [google's email service].
-Hinweis: Dieser Beitrag bezieht sich besonders auf Python 2.7, er sollte aber auf Python 2.x anwendbar sein. Haltet Ausschau nach einem Rundgang durch Python 3, der bald erscheinen soll.
+Hinweis: Dieser Beitrag bezieht sich implizit auf Python 3. Falls du lieber Python 2.7 lernen möchtest, schau [hier](http://learnxinyminutes.com/docs/pythonlegacy/) weiter. Beachte hierbei,
+dass Python 2 als veraltet gilt und für neue Projekte nicht mehr verwendet werden sollte.
```python
+
# Einzeilige Kommentare beginnen mit einer Raute (Doppelkreuz)
-""" Mehrzeilige Strings werden mit
+
+""" Mehrzeilige Strings werden mit
drei '-Zeichen geschrieben und werden
oft als Kommentare genutzt.
"""
@@ -33,15 +37,24 @@ Hinweis: Dieser Beitrag bezieht sich besonders auf Python 2.7, er sollte aber au
1 + 1 #=> 2
8 - 1 #=> 7
10 * 2 #=> 20
-35 / 5 #=> 7
-# Division ist ein wenig kniffliger. Ganze Zahlen werden ohne Rest dividiert
-# und das Ergebnis wird automatisch abgerundet.
-5 / 2 #=> 2
+# Außer Division, welche automatisch Gleitkommazahlen zurückgibt
+35 / 5 # => 7.0
+
+# Eine Division kann mit "//" für positive sowie negative Werte abgerundet werden.
+5 // 3 # => 1
+5.0 // 3.0 # => 1.0 # funktioniert auch mit floats
+-5 // 3 # => -2
+-5.0 // 3.0 # => -2.0
+
+# Benutzt man eine Gleitkommazahl, ist auch das Ergebnis eine solche
+3 * 2.0 # => 6.0
+
+# Der Rest einer Division
+7 % 3 # => 1
-# Um das zu ändern, müssen wir Gleitkommazahlen einführen und benutzen
-2.0 # Das ist eine Gleitkommazahl
-11.0 / 4.0 #=> 2.75 Ahhh...schon besser
+# Potenz
+2**4 # => 16
# Rangfolge wird mit Klammern erzwungen
(1 + 3) * 2 #=> 8
@@ -54,6 +67,18 @@ False
not True #=> False
not False #=> True
+# Boolesche Operatoren
+# Hinweis: "and" und "or" müssen klein geschrieben werden
+True and False #=> False
+False or True #=> True
+
+# Für die Benutzung von Booleschen Operatoren und ganzen Zahlen
+0 and 2 #=> 0
+-5 or 0 #=> -5
+0 == False #=> True
+2 == True #=> False
+1 == True #=> True
+
# Gleichheit ist ==
1 == 1 #=> True
2 == 1 #=> False
@@ -76,58 +101,59 @@ not False #=> True
"Das ist ein String."
'Das ist auch ein String.'
-# Strings können addiert werden!
-"Hello " + "world!" #=> "Hello world!"
+# Strings können auch addiert werden! Vermeide dies aber lieber.
+"Hallo " + "Welt!" #=> "Hallo Welt!"
+# Strings können ohne "+" addiert werden
+"Hallo " "welt!" # => "Hallo Welt!"
# Ein String kann wie eine Liste von Zeichen verwendet werden
"Das ist ein String"[0] #=> 'D'
-# Mit % können Strings formatiert werden, etwa so:
-"%s können %s werden" % ("Strings", "interpoliert")
+# .format kann Strings formatieren
+"{} können {} werden".format("Strings", "formatiert")
+
+# Schneller geht das mit Wiederholungen
+"{0} mag Spagetthi, {0} liebt es zu Schwimmen und ganz besonders mag {0} {1}".format("Hans", "Blattsalat")
+#=> "Hans mag Spagetthi, Hans liebt es zu Schwimmen und ganz besonders mag Hans Blattsalat"
-# Ein modernerer Weg, um Strings zu formatieren, ist die format-Methode.
-# Diese Methode wird bevorzugt
-"{0} können {1} werden".format("Strings", "formatiert")
-# Wir können Schlüsselwörter verwenden, wenn wir nicht abzählen wollen.
-"{name} will {food} essen".format(name="Bob", food="Lasagne")
+# Die Formatierung kann auch mit `f-strings` oder formattierten Strings gemacht
+# werden (ab Python 3.6+)
+name = "Sandra"
+f"Sie hat gesagt, ihr name sei {name}." # => Sie hat gesagt, ihr Name sei Sandra."
+# Es ist möglich, andere Anweisungen innerhalb der geschweiften Klammern zu
+# setzen, welche dann im Output des Strings angezeigt werden.
+f"{name} ist {len(name)} Zeichen lang" # => Sandra ist 6 Zeichen lang.
# None ist ein Objekt
None #=> None
# Verwendet nicht das Symbol für Gleichheit `==`, um Objekte mit None zu vergleichen
-# Benutzt stattdessen `is`
+# Benutzt stattdessen `is`. Dieser Operator testet Objektidentität
"etc" is None #=> False
None is None #=> True
-# Der 'is'-Operator testet Objektidentität. Das ist nicht
-# sehr nützlich, wenn wir mit primitiven Datentypen arbeiten, aber
-# sehr nützlich bei Objekten.
-
# None, 0, und leere Strings/Listen werden alle als False bewertet.
# Alle anderen Werte sind True
-0 == False #=> True
-"" == False #=> True
-
+bool(0) # => False
+bool("") # => False
+bool([]) #=> False
+bool({}) #=> False
####################################################
## 2. Variablen und Collections
####################################################
# Textausgabe ist sehr einfach
-print "Ich bin Python. Schön, dich kennenzulernen!"
-
+print("Ich bin Python. Schön, dich kennenzulernen!")
# Es gibt keinen Grund, Variablen vor der Zuweisung zu deklarieren.
some_var = 5 # kleinschreibung_mit_unterstrichen entspricht der Norm
some_var #=> 5
-# Das Ansprechen einer noch nicht deklarierte Variable löst eine Exception aus.
+# Das Ansprechen einer noch nicht deklarierten Variable löst eine Exception aus.
# Unter "Kontrollstruktur" kann noch mehr über
# Ausnahmebehandlung erfahren werden.
-some_other_var # Löst einen NameError aus
-
-# if kann als Ausdruck verwendet werden
-"yahoo!" if 3 > 2 else 2 #=> "yahoo!"
+some_unknown_var # Löst einen NameError aus
# Listen speichern Sequenzen
li = []
@@ -150,7 +176,7 @@ li[0] #=> 1
li[-1] #=> 3
# Bei Zugriffen außerhalb der Liste kommt es jedoch zu einem IndexError
-li[4] # Raises an IndexError
+li[4] # Verursacht einen IndexError
# Wir können uns Ranges mit Slice-Syntax ansehen
li[1:3] #=> [2, 4]
@@ -158,6 +184,12 @@ li[1:3] #=> [2, 4]
li[2:] #=> [4, 3]
# Das Ende auslassen
li[:3] #=> [1, 2, 4]
+# Jeden Zweiten Eintrag auswählen
+li[::2] # =>[1, 4]
+# Eine umgekehrte Kopie zurückgeben
+li[::-1] # => [3, 4, 2, 1]
+# Jegliche Kombination dieser Syntax machen fortgeschrittene Slices möglich
+# li[Start:Ende:Schritt]
# Ein bestimmtes Element mit del aus der Liste entfernen
del li[2] # li ist jetzt [1, 2, 3]
@@ -174,7 +206,6 @@ li.extend(other_li) # Jetzt ist li [1, 2, 3, 4, 5, 6]
# Die Länge der Liste mit len ermitteln
len(li) #=> 6
-
# Tupel sind wie Listen, nur unveränderlich.
tup = (1, 2, 3)
tup[0] #=> 1
@@ -190,11 +221,10 @@ tup[:2] #=> (1, 2)
a, b, c = (1, 2, 3) # a ist jetzt 1, b ist jetzt 2 und c ist jetzt 3
# Tupel werden standardmäßig erstellt, wenn wir uns die Klammern sparen
d, e, f = 4, 5, 6
-# Es ist kinderleicht zwei Werte zu tauschen
-e, d = d, e # d is now 5 and e is now 4
+# Es ist kinderleicht, zwei Werte zu tauschen
+e, d = d, e # d ist nun 5 und e ist nun 4
-
-# Dictionarys (Wörterbucher) speichern Key-Value-Paare
+# Dictionarys (Wörterbucher) speichern Schlüssel-Werte-Paare
empty_dict = {}
# Hier ein gefülltes Wörterbuch
filled_dict = {"one": 1, "two": 2, "three": 3}
@@ -203,15 +233,15 @@ filled_dict = {"one": 1, "two": 2, "three": 3}
filled_dict["one"] #=> 1
# So holen wir alle Keys (Schlüssel) als Liste
-filled_dict.keys() #=> ["three", "two", "one"]
+list(filled_dict.keys()) #=> ["three", "two", "one"]
# Hinweis - Die Reihenfolge von Schlüsseln in der Liste ist nicht garantiert.
# Einzelne Resultate können anders angeordnet sein.
# Alle Values (Werte) als Liste
-filled_dict.values() #=> [3, 2, 1]
+list(filled_dict.values()) #=> [3, 2, 1]
# Hinweis - Hier gelten dieselben Einschränkungen für die Reihenfolge wie bei Schlüsseln.
-# Das Vorhandensein eines Schlüssels im Wörterbuch mit in prüfen
+# Das Vorhandensein eines Schlüssels im Wörterbuch mit "in" prüfen
"one" in filled_dict #=> True
1 in filled_dict #=> False
@@ -229,17 +259,23 @@ filled_dict.get("four", 4) #=> 4
filled_dict.setdefault("five", 5) #filled_dict["five"] wird auf 5 gesetzt
filled_dict.setdefault("five", 6) #filled_dict["five"] ist noch immer 5
+# Einträge zu einem Wörterbuch hinzufügen
+filled_dict.update({"four":4}) #=> {"one": 1, "two": 2, "three": 3, "four": 4}
+#filled_dict["four"] = 4 # noch ein Weg, Werte hinzuzufügen
+
+# Schlüssel von einem Wörterbuch entfernen
+del filled_dict["one"] # Entfert den Schlüssel "one"
# Sets speichern Mengen
empty_set = set()
# Initialisieren wir ein Set mit ein paar Werten
-some_set = set([1,2,2,3,4]) # some_set ist jetzt set([1, 2, 3, 4])
+some_set = {1, 1, 2, 2, 3, 4} # some_set ist jetzt {1, 2, 3, 4}
-# Seit Python 2.7 kann {} benutzt werden, um ein Set zu erstellen
-filled_set = {1, 2, 2, 3, 4} # => {1 2 3 4}
+# Neue Variablen können einer Menge gleichgesetzt werden
+filled_set = some_set
# Mehr Elemente hinzufügen
-filled_set.add(5) # filled_set is now {1, 2, 3, 4, 5}
+filled_set.add(5) # filled_set ist jetzt {1, 2, 3, 4, 5}
# Schnittmengen werden mit & gebildet
other_set = {3, 4, 5, 6}
@@ -257,7 +293,7 @@ filled_set | other_set #=> {1, 2, 3, 4, 5, 6}
####################################################
-## 3. Kontrollstruktur
+## 3. Kontrollstruktur und Iteratoren
####################################################
# Erstellen wir mal eine Variable
@@ -266,11 +302,11 @@ some_var = 5
# Hier eine if-Anweisung. Die Einrückung ist in Python wichtig!
# gibt "some_var ist kleiner als 10" aus
if some_var > 10:
- print "some_var ist viel größer als 10."
+ print("some_var ist viel größer als 10.")
elif some_var < 10: # Dieser elif-Absatz ist optional.
- print "some_var ist kleiner als 10."
+ print("some_var ist kleiner als 10.")
else: # Das hier ist auch optional.
- print "some_var ist tatsächlich 10."
+ print("some_var ist tatsächlich 10.")
"""
@@ -281,9 +317,9 @@ Ausgabe:
maus ist ein Säugetier
"""
for animal in ["hund", "katze", "maus"]:
- # Wir können Strings mit % formatieren
- print "%s ist ein Säugetier" % animal
-
+ # Wir können Strings mit format() formatieren
+ print("{} ist ein Säugetier".format(animal))
+
"""
`range(Zahl)` gibt eine null-basierte Liste bis zur angegebenen Zahl wieder
Ausgabe:
@@ -293,7 +329,18 @@ Ausgabe:
3
"""
for i in range(4):
- print i
+ print(i)
+
+"""
+"range(unten, oben)" gibt eine Liste von der unteren Zahl bis zur oberen Zahl aus
+Ausgabe:
+ 4
+ 5
+ 6
+ 7
+"""
+for i in range(4, 8):
+ print(i)
"""
While-Schleifen laufen, bis eine Bedingung erfüllt ist.
@@ -305,18 +352,59 @@ Ausgabe:
"""
x = 0
while x < 4:
- print x
+ print(x)
x += 1 # Kurzform für x = x + 1
# Ausnahmebehandlung mit einem try/except-Block
-
-# Funktioniert in Python 2.6 und höher:
try:
# Mit raise wird ein Fehler ausgegeben
raise IndexError("Das hier ist ein Index-Fehler")
except IndexError as e:
pass # Pass ist nur eine no-op. Normalerweise würden wir hier den Fehler klären.
+except (TypeError, NameError):
+ pass # Mehrere Fehler können zusammen geklärt werden, falls erforderlich.
+else: # Optional, hinter allen except-Blöcken
+ print("Keine Probleme!") # Wird nur ausgeführt, wenn keine Ausnahmen aufgetreten sind
+finally: # Wird immer ausgeführt
+ print("Hier können wir Ressourcen aufräumen")
+
+# alternativ zu einem try/finally Block um Aufzuräumen:
+with open("meineDatei.txt") as f:
+ for line in f:
+ print(line)
+
+# Python bietet ein fundamentales Konzept der Iteration.
+# Das Objekt, auf das die Iteration, also die Wiederholung einer Methode
+# angewandt wird, heißt auf Englisch "iterable".
+# Die range Methode gibt ein solches Objekt aus.
+
+filled_dict = {"one": 1, "two": 2, "three": 3}
+our_iterable = filled_dict.keys()
+print(our_iterable) #=> range(1,10). Dies ist ein "iterable" Objekt.
+
+# Über dieses können wir auch iterieren
+for i in our_iterable:
+ print(i) # Gibt one, two, three aus
+
+# Allerdings können wir die einzelnen Elemente nicht mit ihrem Index ausgeben
+our_iterable[1] # TypeError
+# Ein iterable ist ein Objekt, das weiß wie es einen Iteratoren erschafft.
+our_iterator = iter(our_iterable)
+
+# Unser Iterator ist ein Objekt, das sich merkt, welchen Status es gerade hat
+# während wir durch es gehen. Das jeweils nächste Objekt bekommen wir mit "next()"
+next(our_iterator) #=> "one"
+
+# Es hält den vorherigen Status
+next(our_iterator) #=> "two"
+next(our_iterator) #=> "three"
+
+# Nachdem alle Daten ausgegeben worden sind, kommt eine StopIterator Ausnahme zurück
+next(our_iterator) # Gibt StopIteration aus
+
+# Alle Elemente können mit "list()" ausgegeben werden
+list(filled_dict.keys()) #=> ["one", "two", "three"]
####################################################
## 4. Funktionen
@@ -324,7 +412,7 @@ except IndexError as e:
# Mit def neue Funktionen erstellen
def add(x, y):
- print "x ist %s und y ist %s" % (x, y)
+ print("x ist %s und y ist %s" % (x, y))
return x + y # Werte werden mit return zurückgegeben
# Funktionen mit Parametern aufrufen
@@ -348,10 +436,10 @@ def keyword_args(**kwargs):
# Rufen wir es mal auf, um zu sehen, was passiert
keyword_args(big="foot", loch="ness") #=> {"big": "foot", "loch": "ness"}
-# Wir können beides gleichzeitig machem, wenn wir wollen
+# Wir können beides gleichzeitig machen, wenn wir wollen
def all_the_args(*args, **kwargs):
- print args
- print kwargs
+ print(args)
+ print(kwargs)
"""
all_the_args(1, 2, a=3, b=4) Ausgabe:
(1, 2)
@@ -366,6 +454,25 @@ all_the_args(*args) # äquivalent zu foo(1, 2, 3, 4)
all_the_args(**kwargs) # äquivalent zu foo(a=3, b=4)
all_the_args(*args, **kwargs) # äquivalent zu foo(1, 2, 3, 4, a=3, b=4)
+
+# Anwendungsbereich von Funktionen
+x = 5
+
+def setX(num):
+ # lokale Variable x ist nicht die globale Variable x
+ x = num # => 43
+ print (x) # => 43
+
+def setGlobalX(num):
+ global x
+ print (x) # => 5
+ x = num # globale Variable x ist jetzt 6
+ print (x) # => 6
+
+setX(43)
+setGlobalX(6)
+
+
# Python hat First-Class-Funktionen
def create_adder(x):
def adder(y):
@@ -403,7 +510,7 @@ class Human(object):
# Eine Instanzmethode. Alle Methoden erhalten self als erstes Argument.
def say(self, msg):
- return "%s: %s" % (self.name, msg)
+ return "{name}: {message}".format(name=self.name, message=msg)
# Eine Klassenmethode wird von allen Instanzen geteilt.
# Sie werden mit der aufrufenden Klasse als erstem Argument aufgerufen
@@ -419,10 +526,10 @@ class Human(object):
# Eine Instanz einer Klasse erstellen
i = Human(name="Ian")
-print i.say("hi") # gibt "Ian: hi" aus
+print(i.say("hi")) # gibt "Ian: hi" aus
j = Human("Joel")
-print j.say("hello") #gibt "Joel: hello" aus
+print(j.say("hello")) #gibt "Joel: hello" aus
# Rufen wir mal unsere Klassenmethode auf
i.get_species() #=> "H. sapiens"
@@ -442,12 +549,12 @@ Human.grunt() #=> "*grunt*"
# Wir können Module importieren
import math
-print math.sqrt(16) #=> 4
+print(math.sqrt(16)) #=> 4.0
# Wir können auch nur spezielle Funktionen eines Moduls importieren
from math import ceil, floor
-print ceil(3.7) #=> 4.0
-print floor(3.7) #=> 3.0
+print(ceil(3.7)) #=> 4.0
+print(floor(3.7)) #=> 3.0
# Wir können auch alle Funktionen eines Moduls importieren
# Warnung: Dies wird nicht empfohlen
@@ -458,7 +565,7 @@ import math as m
math.sqrt(16) == m.sqrt(16) #=> True
# Module sind in Python nur gewöhnliche Dateien. Wir
-# können unsere eigenen schreiben und importieren. Der Name des
+# können unsere eigenen schreiben und importieren. Der Name des
# Moduls ist der Dateiname.
# Wir können auch die Funktionen und Attribute eines
@@ -466,6 +573,56 @@ math.sqrt(16) == m.sqrt(16) #=> True
import math
dir(math)
+####################################################
+## 7. Fortgeschritten
+####################################################
+
+# Generatoren helfen, um Code schnell und einfach zu schreiben
+def double_numbers(iterable):
+ for i in iterable:
+ yield i + i
+
+# Ein Generator erschafft Werte spontan
+# Statt alle Werte auf einmal, wird bei jeder Iteration einer erschaffen.
+# iteration. Das heißt, Werte größer als 15 werden nicht behandelt.
+# Die range-Methode ist auch ein Generator. Im Fall einer Liste von 1-900000000
+# würde das sehr viel Zeit in Anspruch nehmen.
+# Wenn wir eine Variable mit einem Namen erschaffen wollen, das
+# normalerweise mit einem Python - Schlüsselwort kollidieren würde,
+# benutzen wir einen Unterstrich nach dem Wort.
+range_ = range(1, 900000000)
+# Alle Nummern bis zu einem Ergebnis von >=30 werden verdoppelt
+for i in double_numbers(range_):
+ print(i)
+ if i >= 30:
+ break
+
+# Dekoratoren
+# In diesem Beispiel die Methode beg umwickelt say
+# Beim Aufruf von beg, wird say aufgerufen
+# Falls say_please true ist, ändert sich die ausgegebene Nachricht
+from functools import wraps
+
+
+def beg(target_function):
+ @wraps(target_function)
+ def wrapper(*args, **kwargs):
+ msg, say_please = target_function(*args, **kwargs)
+ if say_please:
+ return "{} {}".format(msg, "Please! I am poor :(")
+ return msg
+
+ return wrapper
+
+
+@beg
+def say(say_please=False):
+ msg = "Can you buy me a beer?"
+ return msg, say_please
+
+
+print(say()) # Can you buy me a beer?
+print(say(say_please=True)) # Can you buy me a beer? Please! I am poor :(
```
@@ -473,15 +630,18 @@ dir(math)
### Kostenlos online (Englisch)
+* [Automate the Boring Stuff with Python](https://automatetheboringstuff.com)
* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/)
* [Dive Into Python](http://www.diveintopython.net/)
-* [The Official Docs](http://docs.python.org/2.6/)
+* [Ideas for Python Projects](http://pythonpracticeprojects.com)
+* [The Official Docs](http://docs.python.org/3/)
* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/)
-* [Python Module of the Week](http://pymotw.com/2/)
+* [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182)
+* [Python Course](http://www.python-course.eu/index.php)
+* [First Steps With Python](https://realpython.com/learn/python-first-steps/)
### Totholz (Englisch)
* [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20)
* [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20)
* [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20)
-
diff --git a/de-de/python3-de.html.markdown b/de-de/python3-de.html.markdown
deleted file mode 100644
index ef1786c8..00000000
--- a/de-de/python3-de.html.markdown
+++ /dev/null
@@ -1,655 +0,0 @@
----
-language: python3
-contributors:
- - ["Louie Dinh", "http://ldinh.ca"]
-translators:
- - ["kultprok", "http:/www.kulturproktologie.de"]
- - ["matthiaskern", "https://github.com/matthiaskern"]
-filename: learnpython3-de.py
-lang: de-de
----
-
-Anmerkungen des ursprünglichen Autors:
-Python wurde in den frühen Neunzigern von Guido van Rossum entworfen. Es ist heute eine der beliebtesten Sprachen. Ich habe mich in Python wegen seiner syntaktischen Übersichtlichkeit verliebt. Eigentlich ist es ausführbarer Pseudocode.
-
-Feedback ist herzlich willkommen! Ihr erreicht mich unter [@louiedinh](http://twitter.com/louiedinh) oder louiedinh [at] [google's email service].
-
-Hinweis: Dieser Beitrag bezieht sich insplizit auf Python 3. Falls du lieber Python 2.7 lernen möchtest, schau [hier](http://learnxinyminutes.com/docs/python/) weiter.
-
-```python
-
-# Einzeilige Kommentare beginnen mit einer Raute (Doppelkreuz)
-
-""" Mehrzeilige Strings werden mit
- drei '-Zeichen geschrieben und werden
- oft als Kommentare genutzt.
-"""
-
-####################################################
-## 1. Primitive Datentypen und Operatoren
-####################################################
-
-# Die Zahlen
-3 #=> 3
-
-# Mathematik funktioniert so, wie man das erwartet
-1 + 1 #=> 2
-8 - 1 #=> 7
-10 * 2 #=> 20
-
-# Außer Division, welche automatisch Gleitkommazahlen zurückgibt
-35 / 5 # => 7.0
-
-# Eine Division kann mit "//" für positive sowie negative Werte abgerundet werden.
-5 // 3 # => 1
-5.0 // 3.0 # => 1.0 # works on floats too
--5 // 3 # => -2
--5.0 // 3.0 # => -2.0
-
-# Benutzt man eine Gleitkommazahl, ist auch das Ergebnis eine solche
-3 * 2.0 # => 6.0
-
-# Der Rest einer Division
-7 % 3 # => 1
-
-# Potenz
-2**4 # => 16
-
-# Rangfolge wird mit Klammern erzwungen
-(1 + 3) * 2 #=> 8
-
-# Boolesche Ausdrücke sind primitive Datentypen
-True
-False
-
-# Mit not wird negiert
-not True #=> False
-not False #=> True
-
-# Boolesche Operatoren
-# Hinweis: "and" und "or" müssen klein geschrieben werden
-True and False #=> False
-False or True #=> True
-
-# Für die Benutzung von Booleschen Operatoren und ganzen Zahlen
-0 and 2 #=> 0
--5 or 0 #=> -5
-0 == False #=> True
-2 == True #=> False
-1 == True #=> True
-
-# Gleichheit ist ==
-1 == 1 #=> True
-2 == 1 #=> False
-
-# Ungleichheit ist !=
-1 != 1 #=> False
-2 != 1 #=> True
-
-# Ein paar weitere Vergleiche
-1 < 10 #=> True
-1 > 10 #=> False
-2 <= 2 #=> True
-2 >= 2 #=> True
-
-# Vergleiche können verknüpft werden!
-1 < 2 < 3 #=> True
-2 < 3 < 2 #=> False
-
-# Strings werden mit " oder ' gebildet
-"Das ist ein String."
-'Das ist auch ein String.'
-
-# Strings können auch addiert werden! Vermeide dies aber lieber.
-"Hallo " + "Welt!" #=> "Hallo Welt!"
-# Strings können ohne "+" addiert werden
-"Hallo " "welt!" # => "Hallo Welt!"
-
-# Ein String kann wie eine Liste von Zeichen verwendet werden
-"Das ist ein String"[0] #=> 'D'
-
-# .format kann Strings formatieren
-"{} können {} werden".format("Strings", "formatiert")
-
-# Schneller geht das mit Wiederholungen
-"{0} mag Spagetthi, {0} liebt es zu Schwimmen und ganz besonders mag {0} {1}".format("Hans", "Blattsalat")
-#=> "Hans mag Spagetthi, Hans liebt es zu Schwimmen und ganz besonders mag Hans Blattsalat"
-
-# Wir können Schlüsselwörter verwenden, wenn wir nicht abzählen wollen.
-"{name} will {food} essen".format(name="Bob", food="Lasagne")
-#=> "Bob will Lasagne kochen"
-
-#Falls dein Python 3 Code auch unter Python 2.5 oder darunter laufen soll, kann das alte Format benutzt werden:
-"%s können %s werden" % ("Strings", "interpoliert")
-
-
-# None ist ein Objekt
-None #=> None
-
-# Verwendet nicht das Symbol für Gleichheit `==`, um Objekte mit None zu vergleichen
-# Benutzt stattdessen `is`. Dieser Operator testet Objektidentität
-"etc" is None #=> False
-None is None #=> True
-
-
-
-# None, 0, und leere Strings/Listen werden alle als False bewertet.
-# Alle anderen Werte sind True
-bool(0) # => False
-bool("") # => False
-bool([]) #=> False
-bool({}) #=> False
-
-
-####################################################
-## 2. Variablen und Collections
-####################################################
-
-# Textausgabe ist sehr einfach
-print "Ich bin Python. Schön, dich kennenzulernen!"
-
-# Es gibt keinen Grund, Variablen vor der Zuweisung zu deklarieren.
-some_var = 5 # kleinschreibung_mit_unterstrichen entspricht der Norm
-some_var #=> 5
-
-# Das Ansprechen einer noch nicht deklarierte Variable löst eine Exception aus.
-# Unter "Kontrollstruktur" kann noch mehr über
-# Ausnahmebehandlung erfahren werden.
-some_unknown_var # Löst einen NameError aus
-
-# Listen speichern Sequenzen
-li = []
-# Wir können mit einer bereits gefüllten Liste anfangen
-other_li = [4, 5, 6]
-
-# append fügt Daten am Ende der Liste ein
-li.append(1) #li ist jetzt [1]
-li.append(2) #li ist jetzt [1, 2]
-li.append(4) #li ist jetzt [1, 2, 4]
-li.append(3) #li ist jetzt [1, 2, 4, 3]
-# Vom Ende der Liste mit pop entfernen
-li.pop() #=> 3 und li ist jetzt [1, 2, 4]
-# und dann wieder hinzufügen
-li.append(3) # li ist jetzt wieder [1, 2, 4, 3].
-
-# Greife auf Listen wie auf Arrays zu
-li[0] #=> 1
-# Das letzte Element ansehen
-li[-1] #=> 3
-
-# Bei Zugriffen außerhalb der Liste kommt es jedoch zu einem IndexError
-li[4] # Verursacht einen IndexError
-
-# Wir können uns Ranges mit Slice-Syntax ansehen
-li[1:3] #=> [2, 4]
-# Den Anfang auslassen
-li[2:] #=> [4, 3]
-# Das Ende auslassen
-li[:3] #=> [1, 2, 4]
-# Jeden Zweiten Eintrag auswählen
-li[::2] # =>[1, 4]
-# Eine umgekehrte Kopie zurückgeben
-li[::-1] # => [3, 4, 2, 1]
-# Jegliche Kombination dieser Syntax machen fortgeschrittene Slices möglich
-# li[Start:Ende:Schritt]
-
-# Ein bestimmtes Element mit del aus der Liste entfernen
-del li[2] # li ist jetzt [1, 2, 3]
-
-# Listen können addiert werden
-li + other_li #=> [1, 2, 3, 4, 5, 6] - Hinweis: li und other_li werden in Ruhe gelassen
-
-# Listen mit extend verknüpfen
-li.extend(other_li) # Jetzt ist li [1, 2, 3, 4, 5, 6]
-
-# Mit in auf Existenz eines Elements prüfen
-1 in li #=> True
-
-# Die Länge der Liste mit len ermitteln
-len(li) #=> 6
-
-
-# Tupel sind wie Listen, nur unveränderlich.
-tup = (1, 2, 3)
-tup[0] #=> 1
-tup[0] = 3 # Löst einen TypeError aus
-
-# Wir können all diese Listen-Dinge auch mit Tupeln anstellen
-len(tup) #=> 3
-tup + (4, 5, 6) #=> (1, 2, 3, 4, 5, 6)
-tup[:2] #=> (1, 2)
-2 in tup #=> True
-
-# Wir können Tupel (oder Listen) in Variablen entpacken
-a, b, c = (1, 2, 3) # a ist jetzt 1, b ist jetzt 2 und c ist jetzt 3
-# Tupel werden standardmäßig erstellt, wenn wir uns die Klammern sparen
-d, e, f = 4, 5, 6
-# Es ist kinderleicht zwei Werte zu tauschen
-e, d = d, e # d is now 5 and e is now 4
-
-
-# Dictionarys (Wörterbucher) speichern Schlüssel-Werte-Paare
-empty_dict = {}
-# Hier ein gefülltes Wörterbuch
-filled_dict = {"one": 1, "two": 2, "three": 3}
-
-# Wir können Einträge mit [] nachschlagen
-filled_dict["one"] #=> 1
-
-# So holen wir alle Keys (Schlüssel) als Liste
-list(filled_dict.keys()) #=> ["three", "two", "one"]
-# Hinweis - Die Reihenfolge von Schlüsseln in der Liste ist nicht garantiert.
-# Einzelne Resultate können anders angeordnet sein.
-
-# Alle Values (Werte) als Liste
-list(filled_dict.values()) #=> [3, 2, 1]
-# Hinweis - Hier gelten dieselben Einschränkungen für die Reihenfolge wie bei Schlüsseln.
-
-# Das Vorhandensein eines Schlüssels im Wörterbuch mit "in" prüfen
-"one" in filled_dict #=> True
-1 in filled_dict #=> False
-
-# Einen nicht vorhandenenen Schlüssel zu suchen, löst einen KeyError aus
-filled_dict["four"] # KeyError
-
-# Mit der get-Methode verhindern wir das
-filled_dict.get("one") #=> 1
-filled_dict.get("four") #=> None
-# Die get-Methode unterstützt auch ein Standardargument, falls der Wert fehlt
-filled_dict.get("one", 4) #=> 1
-filled_dict.get("four", 4) #=> 4
-
-# Die setdefault-Methode ist ein sicherer Weg, ein neues Schlüssel-Wert-Paar anzulegen
-filled_dict.setdefault("five", 5) #filled_dict["five"] wird auf 5 gesetzt
-filled_dict.setdefault("five", 6) #filled_dict["five"] ist noch immer 5
-
-# Einträge zu einem Wörterbuch hinzufügen
-filled_dict.update({"four":4}) #=> {"one": 1, "two": 2, "three": 3, "four": 4}
-#filled_dict["four"] = 4 # noch ein Weg, Werte hinzuzufügen
-
-# Schlüssel von einem Wörterbuch entfernen
-del filled_dict["one"] # Entfert den Schlüssel "one"
-
-
-# Sets speichern Mengen
-empty_set = set()
-# Initialisieren wir ein Set mit ein paar Werten
-some_set = {1, 1, 2, 2, 3, 4} # some_set ist jetzt {1, 2, 3, 4}
-
-# Neue Variablen können einer Menge gleichgesetzt werden
-filled_set = some_set
-
-# Mehr Elemente hinzufügen
-filled_set.add(5) # filled_set ist jetzt {1, 2, 3, 4, 5}
-
-# Schnittmengen werden mit & gebildet
-other_set = {3, 4, 5, 6}
-filled_set & other_set #=> {3, 4, 5}
-
-# Mengen werden mit | vereinigt
-filled_set | other_set #=> {1, 2, 3, 4, 5, 6}
-
-# Die Differenz einer Menge mit - bilden
-{1,2,3,4} - {2,3,5} #=> {1, 4}
-
-# Auf Vorhandensein von Elementen mit in prüfen
-2 in filled_set #=> True
-10 in filled_set #=> False
-
-
-####################################################
-## 3. Kontrollstruktur und Iteratoren
-####################################################
-
-# Erstellen wir mal eine Variable
-some_var = 5
-
-# Hier eine if-Anweisung. Die Einrückung ist in Python wichtig!
-# gibt "some_var ist kleiner als 10" aus
-if some_var > 10:
- print "some_var ist viel größer als 10."
-elif some_var < 10: # Dieser elif-Absatz ist optional.
- print "some_var ist kleiner als 10."
-else: # Das hier ist auch optional.
- print "some_var ist tatsächlich 10."
-
-
-"""
-For-Schleifen iterieren über Listen
-Ausgabe:
- hund ist ein Säugetier
- katze ist ein Säugetier
- maus ist ein Säugetier
-"""
-for animal in ["hund", "katze", "maus"]:
- # Wir können Strings mit format() formatieren
- print("{} ist ein Säugetier".format(animal))
-
-"""
-`range(Zahl)` gibt eine null-basierte Liste bis zur angegebenen Zahl wieder
-Ausgabe:
- 0
- 1
- 2
- 3
-"""
-for i in range(4):
- print i
-
-"""
-"range(unten, oben)" gibt eine Liste von der unteren Zahl bis zur oberen Zahl aus
-Ausgabe:
- 4
- 5
- 6
- 7
-"""
-for i in range(4, 8):
- print(i)
-
-"""
-While-Schleifen laufen, bis eine Bedingung erfüllt ist.
-Ausgabe:
- 0
- 1
- 2
- 3
-"""
-x = 0
-while x < 4:
- print x
- x += 1 # Kurzform für x = x + 1
-
-# Ausnahmebehandlung mit einem try/except-Block
-try:
- # Mit raise wird ein Fehler ausgegeben
- raise IndexError("Das hier ist ein Index-Fehler")
-except IndexError as e:
- pass # Pass ist nur eine no-op. Normalerweise würden wir hier den Fehler klären.
-except (TypeError, NameError):
- pass # Mehrere Fehler können zusammen geklärt werden, falls erforderlich.
-else: # Optional, hinter allen except-Blöcken
- print("Keine Probleme!") # Wird nur ausgeführt, wenn keine Ausnahmen aufgetreten sind
-finally: # Wird immer ausgeführt
- print("Hier können wir Ressourcen aufräumen")
-
-# alternativ zu einem try/finally Block um Aufzuräumen:
-with open("meineDatei.txt") as f:
- for line in f:
- print(line)
-
-# Python bietet ein fundamentales Konzept der Iteration.
-# Das Objekt, auf das die Interation, also die Wiederholung einer Methode angewandt wird heißt auf Englisch "iterable".
-# Die range Method gibt ein solches Objekt aus.
-
-filled_dict = {"one": 1, "two": 2, "three": 3}
-our_iterable = filled_dict.keys()
-print(our_iterable) #=> range(1,10). Dies ist ein "iterable" Objekt.
-
-# Über dieses können wir auch iterieren
-for i in our_iterable:
- print(i) # Gibt one, two, three aus
-
-# Allerdings können wir die einzelnen Elemente nicht mit ihrem index ausgeben
-our_iterable[1] # TypeError
-
-# Ein iterable ist ein Objekt, das weiß wie es einen Iteratoren erschafft.
-our_iterator = iter(our_iterable)
-
-# Unser Iterator ist ein Objekt, das sich merkt, welchen Status es geraden hat während wir durch es gehen.
-# Das jeweeils nächste Objekt bekommen wir mit "next()"
-next(our_iterator) #=> "one"
-
-# Es hält den vorherigen Status
-next(our_iterator) #=> "two"
-next(our_iterator) #=> "three"
-
-# Nachdem alle Daten ausgegeben worden sind, kommt eine StopIterator Ausnahme zurück
-next(our_iterator) # Gibt StopIteration aus
-
-# Alle Elemente können mit "list()" ausgegeben werden
-list(filled_dict.keys()) #=> ["one", "two", "three"]
-
-
-
-####################################################
-## 4. Funktionen
-####################################################
-
-# Mit def neue Funktionen erstellen
-def add(x, y):
- print "x ist %s und y ist %s" % (x, y)
- return x + y # Werte werden mit return zurückgegeben
-
-# Funktionen mit Parametern aufrufen
-add(5, 6) #=> Ausgabe ist "x ist 5 und y ist 6" und gibt 11 zurück
-
-# Ein anderer Weg des Funktionsaufrufs sind Schlüsselwort-Argumente
-add(y=6, x=5) # Schlüsselwörter können in beliebiger Reihenfolge übergeben werden.
-
-# Wir können Funktionen mit beliebiger Anzahl von # Positionsargumenten definieren
-def varargs(*args):
- return args
-
-varargs(1, 2, 3) #=> (1,2,3)
-
-
-# Wir können auch Funktionen mit beliebiger Anzahl
-# Schlüsselwort-Argumenten definieren
-def keyword_args(**kwargs):
- return kwargs
-
-# Rufen wir es mal auf, um zu sehen, was passiert
-keyword_args(big="foot", loch="ness") #=> {"big": "foot", "loch": "ness"}
-
-# Wir können beides gleichzeitig machem, wenn wir wollen
-def all_the_args(*args, **kwargs):
- print args
- print kwargs
-"""
-all_the_args(1, 2, a=3, b=4) Ausgabe:
- (1, 2)
- {"a": 3, "b": 4}
-"""
-
-# Beim Aufruf von Funktionen können wir das Gegenteil von varargs/kwargs machen!
-# Wir benutzen dann *, um Tupel auszuweiten, und ** für kwargs.
-args = (1, 2, 3, 4)
-kwargs = {"a": 3, "b": 4}
-all_the_args(*args) # äquivalent zu foo(1, 2, 3, 4)
-all_the_args(**kwargs) # äquivalent zu foo(a=3, b=4)
-all_the_args(*args, **kwargs) # äquivalent zu foo(1, 2, 3, 4, a=3, b=4)
-
-
-# Anwendungsbereich von Funktionen
-x = 5
-
-def setX(num):
- # lokale Variable x ist nicht die globale Variable x
- x = num # => 43
- print (x) # => 43
-
-def setGlobalX(num):
- global x
- print (x) # => 5
- x = num # globale Variable x ist jetzt 6
- print (x) # => 6
-
-setX(43)
-setGlobalX(6)
-
-
-# Python hat First-Class-Funktionen
-def create_adder(x):
- def adder(y):
- return x + y
- return adder
-
-add_10 = create_adder(10)
-add_10(3) #=> 13
-
-# Es gibt auch anonyme Funktionen
-(lambda x: x > 2)(3) #=> True
-
-# Es gibt auch Funktionen höherer Ordnung als Built-Ins
-map(add_10, [1,2,3]) #=> [11, 12, 13]
-filter(lambda x: x > 5, [3, 4, 5, 6, 7]) #=> [6, 7]
-
-# Wir können bei map- und filter-Funktionen auch List Comprehensions einsetzen
-[add_10(i) for i in [1, 2, 3]] #=> [11, 12, 13]
-[x for x in [3, 4, 5, 6, 7] if x > 5] #=> [6, 7]
-
-####################################################
-## 5. Klassen
-####################################################
-
-# Wir bilden die Unterklasse eines Objekts, um Klassen zu erhalten.
-class Human(object):
-
- # Ein Klassenattribut. Es wird von allen Instanzen einer Klasse geteilt
- species = "H. sapiens"
-
- # Ein simpler Konstruktor
- def __init__(self, name):
- # Wir weisen das Argument name dem name-Attribut der Instanz zu
- self.name = name
-
- # Eine Instanzmethode. Alle Methoden erhalten self als erstes Argument.
- def say(self, msg):
- return "{name}: {message}".format(name=self.name, message=msg)
-
- # Eine Klassenmethode wird von allen Instanzen geteilt.
- # Sie werden mit der aufrufenden Klasse als erstem Argument aufgerufen
- @classmethod
- def get_species(cls):
- return cls.species
-
- # Eine statische Methode wird ohne Klasse oder Instanz aufgerufen
- @staticmethod
- def grunt():
- return "*grunt*"
-
-
-# Eine Instanz einer Klasse erstellen
-i = Human(name="Ian")
-print i.say("hi") # gibt "Ian: hi" aus
-
-j = Human("Joel")
-print j.say("hello") #gibt "Joel: hello" aus
-
-# Rufen wir mal unsere Klassenmethode auf
-i.get_species() #=> "H. sapiens"
-
-# Ändern wir mal das gemeinsame Attribut
-Human.species = "H. neanderthalensis"
-i.get_species() #=> "H. neanderthalensis"
-j.get_species() #=> "H. neanderthalensis"
-
-# Aufruf der statischen Methode
-Human.grunt() #=> "*grunt*"
-
-
-####################################################
-## 6. Module
-####################################################
-
-# Wir können Module importieren
-import math
-print math.sqrt(16) #=> 4
-
-# Wir können auch nur spezielle Funktionen eines Moduls importieren
-from math import ceil, floor
-print ceil(3.7) #=> 4.0
-print floor(3.7) #=> 3.0
-
-# Wir können auch alle Funktionen eines Moduls importieren
-# Warnung: Dies wird nicht empfohlen
-from math import *
-
-# Wir können Modulnamen abkürzen
-import math as m
-math.sqrt(16) == m.sqrt(16) #=> True
-
-# Module sind in Python nur gewöhnliche Dateien. Wir
-# können unsere eigenen schreiben und importieren. Der Name des
-# Moduls ist der Dateiname.
-
-# Wir können auch die Funktionen und Attribute eines
-# Moduls herausfinden.
-import math
-dir(math)
-
-
-####################################################
-## 7. Fortgeschritten
-####################################################
-
-# Generatoren helfen um Code schnell und einfach zu schreiben
-def double_numbers(iterable):
- for i in iterable:
- yield i + i
-
-# Ein Generator erschafft Werte spontan
-# Statt alle Werte auf einmal, wird bei jeder Iteration einer erschaffen.
-# iteration. Das heißt, Werte größer als 15 werden nicht behandelt.
-# Die range-Methode ist auch ein Generator. Im Fall einer Liste von 1-900000000
-# würde das sehr viel Zeit in Anspruch nehmen.
-# Wenn wir eine variable mit einem Namen erschaffen wollen, das
-# normalerweise mit einem Python - Schlüsselwort kollidieren würde,
-# benutzen wir einen Unterstrich nach dem Wort.
-range_ = range(1, 900000000)
-# Alle Nummern bis zu einem Ergebnis von >=30 werden verdoppelt
-for i in double_numbers(range_):
- print(i)
- if i >= 30:
- break
-
-
-# Dekoratoren
-# In diesem Beispiel die Methode beg umwickelt say
-# Beim Aufruf von beg, say wird aufgerufen
-# Falls say_please true ist, ändert sich die ausgegebene Nachricht
-from functools import wraps
-
-
-def beg(target_function):
- @wraps(target_function)
- def wrapper(*args, **kwargs):
- msg, say_please = target_function(*args, **kwargs)
- if say_please:
- return "{} {}".format(msg, "Please! I am poor :(")
- return msg
-
- return wrapper
-
-
-@beg
-def say(say_please=False):
- msg = "Can you buy me a beer?"
- return msg, say_please
-
-
-print(say()) # Can you buy me a beer?
-print(say(say_please=True)) # Can you buy me a beer? Please! I am poor :(
-
-```
-
-## Lust auf mehr?
-
-### Kostenlos online (Englisch)
-
-* [Automate the Boring Stuff with Python](https://automatetheboringstuff.com)
-* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/)
-* [Dive Into Python](http://www.diveintopython.net/)
-* [Ideas for Python Projects](http://pythonpracticeprojects.com)
-* [The Official Docs](http://docs.python.org/3/)
-* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/)
-* [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182)
-* [Python Course](http://www.python-course.eu/index.php)
-* [First Steps With Python](https://realpython.com/learn/python-first-steps/)
-
-### Totholz (Englisch)
-
-* [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20)
-* [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20)
-* [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20)
diff --git a/de-de/pythonlegacy-de.html.markdown b/de-de/pythonlegacy-de.html.markdown
new file mode 100644
index 00000000..d66a8551
--- /dev/null
+++ b/de-de/pythonlegacy-de.html.markdown
@@ -0,0 +1,766 @@
+---
+language: Python 2 (legacy)
+contributors:
+ - ["Louie Dinh", "http://ldinh.ca"]
+translators:
+ - ["kultprok", "http:/www.kulturproktologie.de"]
+filename: learnpythonlegacy-de.py
+lang: de-de
+---
+
+Anmerkungen des ursprünglichen Autors:
+Python wurde in den frühen Neunzigern von Guido van Rossum entworfen. Es ist heute eine der beliebtesten Sprachen. Ich habe mich in Python wegen seiner syntaktischen Übersichtlichkeit verliebt. Eigentlich ist es ausführbarer Pseudocode.
+
+Feedback ist herzlich willkommen! Ihr erreicht mich unter [@louiedinh](http://twitter.com/louiedinh) oder louiedinh [at] [google's email service]
+
+Hinweis: Dieser Beitrag bezieht sich besonders auf Python 2.7, er sollte aber auf Python 2.x anwendbar sein. Haltet Ausschau nach einem Rundgang durch Python 3, der bald erscheinen soll.
+
+```python
+# Einzeilige Kommentare beginnen mit einer Raute (Doppelkreuz)
+""" Mehrzeilige Strings werden mit
+ drei '-Zeichen geschrieben und werden
+ oft als Kommentare genutzt.
+"""
+
+####################################################
+## 1. Primitive Datentypen und Operatoren
+####################################################
+
+# Die Zahlen
+3 #=> 3
+
+# Mathematik funktioniert so, wie man das erwartet
+1 + 1 #=> 2
+8 - 1 #=> 7
+10 * 2 #=> 20
+35 / 5 #=> 7
+
+# Division ist ein wenig kniffliger. Ganze Zahlen werden ohne Rest dividiert
+# und das Ergebnis wird automatisch abgerundet.
+5 / 2 #=> 2
+
+# Um das zu ändern, müssen wir Gleitkommazahlen einführen und benutzen
+2.0 # Das ist eine Gleitkommazahl
+11.0 / 4.0 #=> 2.75 Ahhh...schon besser
+
+# Rangfolge wird mit Klammern erzwungen
+(1 + 3) * 2 #=> 8
+
+# Boolesche Ausdrücke sind primitive Datentypen
+True
+False
+
+# Mit not wird negiert
+not True #=> False
+not False #=> True
+
+# Gleichheit ist ==
+1 == 1 #=> True
+2 == 1 #=> False
+
+# Ungleichheit ist !=
+1 != 1 #=> False
+2 != 1 #=> True
+
+# Ein paar weitere Vergleiche
+1 < 10 #=> True
+1 > 10 #=> False
+2 <= 2 #=> True
+2 >= 2 #=> True
+
+# Vergleiche können verknüpft werden!
+1 < 2 < 3 #=> True
+2 < 3 < 2 #=> False
+
+# Strings werden mit " oder ' gebildet
+"Das ist ein String."
+'Das ist auch ein String.'
+
+# Strings können addiert werden!
+"Hello " + "world!" #=> "Hello world!"
+
+# Ein String kann wie eine Liste von Zeichen verwendet werden
+"Das ist ein String"[0] #=> 'D'
+
+# Mit % können Strings formatiert werden, etwa so:
+"%s können %s werden" % ("Strings", "interpoliert")
+
+# Ein modernerer Weg, um Strings zu formatieren, ist die format-Methode.
+# Diese Methode wird bevorzugt
+"{0} können {1} werden".format("Strings", "formatiert")
+# Wir können Schlüsselwörter verwenden, wenn wir nicht abzählen wollen.
+"{name} will {food} essen".format(name="Bob", food="Lasagne")
+
+# None ist ein Objekt
+None #=> None
+
+# Verwendet nicht das Symbol für Gleichheit `==`, um Objekte mit None zu vergleichen
+# Benutzt stattdessen `is`
+"etc" is None #=> False
+None is None #=> True
+
+# Der 'is'-Operator testet Objektidentität. Das ist nicht
+# sehr nützlich, wenn wir mit primitiven Datentypen arbeiten, aber
+# sehr nützlich bei Objekten.
+
+# None, 0, und leere Strings/Listen werden alle als False bewertet.
+# Alle anderen Werte sind True
+0 == False #=> True
+"" == False #=> True
+
+
+####################################################
+## 2. Variablen und Collections
+####################################################
+
+# Textausgabe ist sehr einfach
+print "Ich bin Python. Schön, dich kennenzulernen!"
+
+
+# Es gibt keinen Grund, Variablen vor der Zuweisung zu deklarieren.
+some_var = 5 # kleinschreibung_mit_unterstrichen entspricht der Norm
+some_var #=> 5
+
+# Das Ansprechen einer noch nicht deklarierte Variable löst eine Exception aus.
+# Unter "Kontrollstruktur" kann noch mehr über
+# Ausnahmebehandlung erfahren werden.
+some_other_var # Löst einen NameError aus
+
+# if kann als Ausdruck verwendet werden
+"yahoo!" if 3 > 2 else 2 #=> "yahoo!"
+
+# Listen speichern Sequenzen
+li = []
+# Wir können mit einer bereits gefüllten Liste anfangen
+other_li = [4, 5, 6]
+
+# append fügt Daten am Ende der Liste ein
+li.append(1) #li ist jetzt [1]
+li.append(2) #li ist jetzt [1, 2]
+li.append(4) #li ist jetzt [1, 2, 4]
+li.append(3) #li ist jetzt [1, 2, 4, 3]
+# Vom Ende der Liste mit pop entfernen
+li.pop() #=> 3 und li ist jetzt [1, 2, 4]
+# und dann wieder hinzufügen
+li.append(3) # li ist jetzt wieder [1, 2, 4, 3].
+
+# Greife auf Listen wie auf Arrays zu
+li[0] #=> 1
+# Das letzte Element ansehen
+li[-1] #=> 3
+
+# Bei Zugriffen außerhalb der Liste kommt es jedoch zu einem IndexError
+li[4] # Raises an IndexError
+
+# Wir können uns Ranges mit Slice-Syntax ansehen
+li[1:3] #=> [2, 4]
+# Den Anfang auslassen
+li[2:] #=> [4, 3]
+# Das Ende auslassen
+li[:3] #=> [1, 2, 4]
+
+# Ein bestimmtes Element mit del aus der Liste entfernen
+del li[2] # li ist jetzt [1, 2, 3]
+
+# Listen können addiert werden
+li + other_li #=> [1, 2, 3, 4, 5, 6] - Hinweis: li und other_li werden in Ruhe gelassen
+
+# Listen mit extend verknüpfen
+li.extend(other_li) # Jetzt ist li [1, 2, 3, 4, 5, 6]
+
+# Mit in auf Existenz eines Elements prüfen
+1 in li #=> True
+
+# Die Länge der Liste mit len ermitteln
+len(li) #=> 6
+
+
+# Tupel sind wie Listen, nur unveränderlich.
+tup = (1, 2, 3)
+tup[0] #=> 1
+tup[0] = 3 # Löst einen TypeError aus
+
+# Wir können all diese Listen-Dinge auch mit Tupeln anstellen
+len(tup) #=> 3
+tup + (4, 5, 6) #=> (1, 2, 3, 4, 5, 6)
+tup[:2] #=> (1, 2)
+2 in tup #=> True
+
+# Wir können Tupel (oder Listen) in Variablen entpacken
+a, b, c = (1, 2, 3) # a ist jetzt 1, b ist jetzt 2 und c ist jetzt 3
+# Tupel werden standardmäßig erstellt, wenn wir uns die Klammern sparen
+d, e, f = 4, 5, 6
+# Es ist kinderleicht zwei Werte zu tauschen
+e, d = d, e # d is now 5 and e is now 4
+
+
+# Dictionarys (Wörterbucher) speichern Key-Value-Paare
+empty_dict = {}
+# Hier ein gefülltes Wörterbuch
+filled_dict = {"one": 1, "two": 2, "three": 3}
+
+# Wir können Einträge mit [] nachschlagen
+filled_dict["one"] #=> 1
+
+# So holen wir alle Keys (Schlüssel) als Liste
+filled_dict.keys() #=> ["three", "two", "one"]
+# Hinweis - Die Reihenfolge von Schlüsseln in der Liste ist nicht garantiert.
+# Einzelne Resultate können anders angeordnet sein.
+
+# Alle Values (Werte) als Liste
+filled_dict.values() #=> [3, 2, 1]
+# Hinweis - Hier gelten dieselben Einschränkungen für die Reihenfolge wie bei Schlüsseln.
+
+# Das Vorhandensein eines Schlüssels im Wörterbuch mit in prüfen
+"one" in filled_dict #=> True
+1 in filled_dict #=> False
+
+# Einen nicht vorhandenenen Schlüssel zu suchen, löst einen KeyError aus
+filled_dict["four"] # KeyError
+
+# Mit der get-Methode verhindern wir das
+filled_dict.get("one") #=> 1
+filled_dict.get("four") #=> None
+# Die get-Methode unterstützt auch ein Standardargument, falls der Wert fehlt
+filled_dict.get("one", 4) #=> 1
+filled_dict.get("four", 4) #=> 4
+
+# Die setdefault-Methode ist ein sicherer Weg, ein neues Schlüssel-Wert-Paar anzulegen
+filled_dict.setdefault("five", 5) #filled_dict["five"] wird auf 5 gesetzt
+filled_dict.setdefault("five", 6) #filled_dict["five"] ist noch immer 5
+
+
+# Sets speichern Mengen
+empty_set = set()
+# Initialisieren wir ein Set mit ein paar Werten
+some_set = set([1,2,2,3,4]) # some_set ist jetzt set([1, 2, 3, 4])
+
+# Seit Python 2.7 kann {} benutzt werden, um ein Set zu erstellen
+filled_set = {1, 2, 2, 3, 4} # => {1 2 3 4}
+
+# Mehr Elemente hinzufügen
+filled_set.add(5) # filled_set is now {1, 2, 3, 4, 5}
+
+# Schnittmengen werden mit & gebildet
+other_set = {3, 4, 5, 6}
+filled_set & other_set #=> {3, 4, 5}
+
+# Mengen werden mit | vereinigt
+filled_set | other_set #=> {1, 2, 3, 4, 5, 6}
+
+# Die Differenz einer Menge mit - bilden
+{1,2,3,4} - {2,3,5} #=> {1, 4}
+
+# Auf Vorhandensein von Elementen mit in prüfen
+2 in filled_set #=> True
+10 in filled_set #=> False
+
+
+####################################################
+## 3. Kontrollstruktur
+####################################################
+
+# Erstellen wir mal eine Variable
+some_var = 5
+
+# Hier eine if-Anweisung. Die Einrückung ist in Python wichtig!
+# gibt "some_var ist kleiner als 10" aus
+if some_var > 10:
+ print "some_var ist viel größer als 10."
+elif some_var < 10: # Dieser elif-Absatz ist optional.
+ print "some_var ist kleiner als 10."
+else: # Das hier ist auch optional.
+ print "some_var ist tatsächlich 10."
+
+
+"""
+For-Schleifen iterieren über Listen
+Ausgabe:
+ hund ist ein Säugetier
+ katze ist ein Säugetier
+ maus ist ein Säugetier
+"""
+for animal in ["hund", "katze", "maus"]:
+ # Wir können Strings mit % formatieren
+ print "%s ist ein Säugetier" % animal
+
+"""
+`range(Zahl)` gibt eine null-basierte Liste bis zur angegebenen Zahl wieder
+Ausgabe:
+ 0
+ 1
+ 2
+ 3
+"""
+for i in range(4):
+ print i
+
+"""
+While-Schleifen laufen, bis eine Bedingung erfüllt ist.
+Ausgabe:
+ 0
+ 1
+ 2
+ 3
+"""
+x = 0
+while x < 4:
+ print x
+ x += 1 # Kurzform für x = x + 1
+
+# Ausnahmebehandlung mit einem try/except-Block
+
+# Funktioniert in Python 2.6 und höher:
+try:
+ # Mit raise wird ein Fehler ausgegeben
+ raise IndexError("Das hier ist ein Index-Fehler")
+except IndexError as e:
+ pass # Pass ist nur eine no-op. Normalerweise würden wir hier den Fehler klären.
+
+
+####################################################
+## 4. Funktionen
+####################################################
+
+# Mit def neue Funktionen erstellen
+def add(x, y):
+ print "x ist %s und y ist %s" % (x, y)
+ return x + y # Werte werden mit return zurückgegeben
+
+# Funktionen mit Parametern aufrufen
+add(5, 6) #=> Ausgabe ist "x ist 5 und y ist 6" und gibt 11 zurück
+
+# Ein anderer Weg des Funktionsaufrufs sind Schlüsselwort-Argumente
+add(y=6, x=5) # Schlüsselwörter können in beliebiger Reihenfolge übergeben werden.
+
+# Wir können Funktionen mit beliebiger Anzahl von # Positionsargumenten definieren
+def varargs(*args):
+ return args
+
+varargs(1, 2, 3) #=> (1,2,3)
+
+
+# Wir können auch Funktionen mit beliebiger Anzahl
+# Schlüsselwort-Argumenten definieren
+def keyword_args(**kwargs):
+ return kwargs
+
+# Rufen wir es mal auf, um zu sehen, was passiert
+keyword_args(big="foot", loch="ness") #=> {"big": "foot", "loch": "ness"}
+
+# Wir können beides gleichzeitig machem, wenn wir wollen
+def all_the_args(*args, **kwargs):
+ print args
+ print kwargs
+"""
+all_the_args(1, 2, a=3, b=4) Ausgabe:
+ (1, 2)
+ {"a": 3, "b": 4}
+"""
+
+# Beim Aufruf von Funktionen können wir das Gegenteil von varargs/kwargs machen!
+# Wir benutzen dann *, um Tupel auszuweiten, und ** für kwargs.
+args = (1, 2, 3, 4)
+kwargs = {"a": 3, "b": 4}
+all_the_args(*args) # äquivalent zu foo(1, 2, 3, 4)
+all_the_args(**kwargs) # äquivalent zu foo(a=3, b=4)
+all_the_args(*args, **kwargs) # äquivalent zu foo(1, 2, 3, 4, a=3, b=4)
+
+# Python hat First-Class-Funktionen
+def create_adder(x):
+ def adder(y):
+ return x + y
+ return adder
+
+add_10 = create_adder(10)
+add_10(3) #=> 13
+
+# Es gibt auch anonyme Funktionen
+(lambda x: x > 2)(3) #=> True
+
+# Es gibt auch Funktionen höherer Ordnung als Built-Ins
+map(add_10, [1,2,3]) #=> [11, 12, 13]
+filter(lambda x: x > 5, [3, 4, 5, 6, 7]) #=> [6, 7]
+
+# Wir können bei map- und filter-Funktionen auch List Comprehensions einsetzen
+[add_10(i) for i in [1, 2, 3]] #=> [11, 12, 13]
+[x for x in [3, 4, 5, 6, 7] if x > 5] #=> [6, 7]
+
+
+####################################################
+## 5. Module
+####################################################
+
+# Wir können Module importieren
+import math
+print math.sqrt(16) #=> 4.0
+
+# Wir können auch nur spezielle Funktionen eines Moduls importieren
+from math import ceil, floor
+print ceil(3.7) #=> 4.0
+print floor(3.7) #=> 3.0
+
+# Wir können auch alle Funktionen eines Moduls importieren
+# Warnung: Dies wird nicht empfohlen
+from math import *
+
+# Wir können Modulnamen abkürzen
+import math as m
+math.sqrt(16) == m.sqrt(16) #=> True
+
+# Module sind in Python nur gewöhnliche Dateien. Wir
+# können unsere eigenen schreiben und importieren. Der Name des
+# Moduls ist der Dateiname.
+
+# Wir können herausfinden, welche Funktionen und Attribute in einem
+# Modul definiert sind.
+import math
+dir(math)
+
+# Wenn Sie ein Python-Skript namens math.py im selben Ordner
+# wie Ihr aktuelles Skript haben, wird die Datei math.py
+# anstelle des integrierten Python-Moduls geladen.
+# Dies geschieht, weil der lokale Ordner Vorrang
+# vor den in Python integrierten Bibliotheken hat.
+
+
+####################################################
+## 6. Klassen
+####################################################
+
+# Wir verwenden das Schlüsselwort "class" um eine Klasse zu erzeugen.
+class Human(object):
+
+ # Ein Klassenattribut. Es wird von allen Instanzen einer Klasse geteilt
+ species = "H. sapiens"
+
+ # Ein simpler Konstruktor, wird aufgerufen, wenn diese Klasse instanziiert wird.
+ # Beachten Sie, dass die doppelten vorangestellten und nachgestellten
+ # Unterstriche Objekte oder Attribute bezeichnen, die von Python verwendet werden,
+ # aber in benutzergesteuerten Namespaces leben.
+ # Methoden (oder Objekte oder Attribute) wie: __init__, __str__, __repr__ usw.
+ # werden als Sondermethoden (oder manchmal als Dundermethoden bezeichnet) bezeichnet.
+ # Sie sollten solche Namen nicht selbst erfinden.
+ def __init__(self, name):
+ # Wir weisen das Argument name dem name-Attribut der Instanz zu
+ self.name = name
+
+ # Eine Instanzmethode. Alle Methoden erhalten "self" als erstes Argument.
+ def say(self, msg):
+ return "%s: %s" % (self.name, msg)
+
+ # Eine weitere Instanzmethode
+ def sing(self):
+ return 'yo... yo... microphone check... one two... one two...'
+
+ # Eine Klassenmethode wird von allen Instanzen geteilt.
+ # Sie werden mit der aufrufenden Klasse als erstem Argument aufgerufen
+ @classmethod
+ def get_species(cls):
+ return cls.species
+
+ # Eine statische Methode wird ohne Klasse oder Instanz aufgerufen
+ @staticmethod
+ def grunt():
+ return "*grunt*"
+
+ # Eine Eigenschaft (Property) ist wie ein Getter.
+    # Es verwandelt die Methode age() in ein schreibgeschütztes Attribut mit demselben Namen.
+    # Es ist jedoch nicht nötig, triviale Getter und Setter in Python zu schreiben.
+ @property
+ def age(self):
+ return self._age
+
+    # Damit kann die Eigenschaft festgelegt werden
+ @age.setter
+ def age(self, age):
+ self._age = age
+
+    # Damit kann die Eigenschaft gelöscht werden
+ @age.deleter
+ def age(self):
+ del self._age
+
+# Wenn ein Python-Interpreter eine Quelldatei liest, führt er den gesamten Code aus.
+# Diese __name__-Prüfung stellt sicher, dass dieser Codeblock nur ausgeführt wird,
+# wenn dieses Modul das Hauptprogramm ist.
+if __name__ == '__main__':
+ # Eine Instanz einer Klasse erstellen
+ i = Human(name="Ian")
+ i.say("hi") # "Ian: hi"
+ j = Human("Joel")
+ j.say("hello") # "Joel: hello"
+ # i und j sind Instanzen des Typs Mensch, oder anders ausgedrückt: Sie sind Objekte des Menschen
+
+ # Rufen wir unsere Klassenmethode auf
+ i.say(i.get_species()) # "Ian: H. sapiens"
+
+ # Ändern wir das gemeinsame Attribut
+ Human.species = "H. neanderthalensis"
+ i.say(i.get_species()) # => "Ian: H. neanderthalensis"
+ j.say(j.get_species()) # => "Joel: H. neanderthalensis"
+
+ # Aufruf der statischen Methode
+ print(Human.grunt()) # => "*grunt*"
+
+ # Kann keine statische Methode mit Instanz des Objekts aufrufen,
+ # da i.grunt () automatisch "self" (das Objekt i) als Argument verwendet
+ print(i.grunt()) # => TypeError: grunt() takes 0 positional arguments but 1 was given
+
+ # Die Eigenschaft für diese Instanz aktualisieren
+ i.age = 42
+ # die Eigenschaft auslesen
+ i.say(i.age) # => "Ian: 42"
+ j.say(j.age) # => "Joel: 0"
+ # die Eigenschaft löschen
+ del i.age
+ # i.age # => würde einen AttributeError werfen
+
+####################################################
+## 6.1 Inheritance
+####################################################
+
+# Vererbung ermöglicht die Definition neuer untergeordneter Klassen,
+# die Methoden und Variablen von ihrer übergeordneten Klasse erben.
+
+# Wenn Sie die oben definierte Human-Klasse als Basis- oder Elternklasse verwenden,
+# können Sie eine untergeordnete Klasse, Superhero, definieren, die die Klassenvariablen
+# wie "species", "name" und "age" sowie Methoden wie "sing" und "grunzen" aus der Klasse Human erbt.
+# Die Untergeordnete Klasse kann aber auch eigene Eigenschaften haben.
+
+# Um von der Modularisierung per Datei zu profitieren, können Sie die Klassen
+# in ihren eigenen Dateien platzieren, z. B. human.py
+
+# Um Funktionen aus anderen Dateien zu importieren, verwenden Sie das folgende Format
+# from "Dateiname-ohne-Erweiterung" impotr "Funktion-oder-Klasse"
+
+from human import Human
+
+# Geben Sie die übergeordnete(n) Klasse(n) als Parameter für die Klassendefinition an
+class Superhero(Human):
+
+ # Wenn die untergeordnete Klasse alle Definitionen des übergeordneten Elements
+ # ohne Änderungen erben soll, können Sie einfach das Schlüsselwort "pass"
+ # (und nichts anderes) verwenden. In diesem Fall wird jedoch auskommentiert,
+ # um eine eindeutige untergeordnete Klasse zuzulassen:
+ # pass
+
+ # Kindklassen können die Attribute ihrer Eltern überschreiben
+ species = 'Superhuman'
+
+ # Kinder erben automatisch den Konstruktor ihrer übergeordneten Klasse
+ # einschließlich ihrer Argumente, können aber auch zusätzliche Argumente oder
+ # Definitionen definieren und ihre Methoden zB den Klassenkonstruktor überschreiben.
+ # Dieser Konstruktor erbt das Argument "name" von der Klasse "Human" und
+ # fügt die Argumente "superpowers" und "movie" hinzu:
+ def __init__(self, name, movie=False,
+ superpowers=["super strength", "bulletproofing"]):
+
+ # zusätzliche Klassenattribute hinzufügen:
+ self.fictional = True
+ self.movie = movie
+ # Beachten Sie die veränderlichen Standardwerte, da die Standardwerte gemeinsam genutzt werden
+ self.superpowers = superpowers
+
+ # Mit der Funktion "super" können Sie auf die Methoden der übergeordneten Klasse
+ # zugreifen, die vom untergeordneten Objekt überschrieben werden,
+ # in diesem Fall die Methode __init__.
+        # Dies ruft den Konstruktor der übergeordneten Klasse auf:
+ super().__init__(name)
+
+ # überschreiben der "sing" Methode
+ def sing(self):
+ return 'Dun, dun, DUN!'
+
+ # eine zusätzliche Instanzmethode hinzufügen
+ def boast(self):
+ for power in self.superpowers:
+ print("I wield the power of {pow}!".format(pow=power))
+
+if __name__ == '__main__':
+ sup = Superhero(name="Tick")
+
+ # Instanztypprüfungen
+ if isinstance(sup, Human):
+ print('I am human')
+ if type(sup) is Superhero:
+ print('I am a superhero')
+
+ # Die Reihenfolge der Methodenauflösung (MRO = Method Resolution Order) anzeigen, die sowohl von getattr() als auch von super() verwendet wird.
+    # Dieses Attribut ist dynamisch und kann aktualisiert werden.
+ print(Superhero.__mro__) # => (<class '__main__.Superhero'>,
+ # => <class 'human.Human'>, <class 'object'>)
+
+ # Ruft die übergeordnete Methode auf, verwendet jedoch das eigene Klassenattribut
+ print(sup.get_species()) # => Superhuman
+
+ # Ruft die überschriebene Methode auf
+ print(sup.sing()) # => Dun, dun, DUN!
+
+ # Ruft die Methode von Human auf
+ sup.say('Spoon') # => Tick: Spoon
+
+ # Aufruf einer Methode, die nur in Superhero existiert
+ sup.boast() # => I wield the power of super strength!
+ # => I wield the power of bulletproofing!
+
+ # Vererbtes Klassenattribut
+ sup.age = 31
+ print(sup.age) # => 31
+
+ # Attribut, das nur in Superhero existiert
+ print('Am I Oscar eligible? ' + str(sup.movie))
+
+####################################################
+## 6.2 Multiple Inheritance
+####################################################
+
+# Eine weitere Klassendefinition
+# bat.py
+
+class Bat:
+
+ species = 'Baty'
+
+ def __init__(self, can_fly=True):
+ self.fly = can_fly
+
+ # This class also has a say method
+ def say(self, msg):
+ msg = '... ... ...'
+ return msg
+
+ # And its own method as well
+ def sonar(self):
+ return '))) ... ((('
+
+if __name__ == '__main__':
+ b = Bat()
+ print(b.say('hello'))
+ print(b.fly)
+
+# Und noch eine andere Klassendefinition, die von Superhero und Bat erbt
+# superhero.py
+from superhero import Superhero
+from bat import Bat
+
+# Definieren Sie Batman als eine Kindklasse, das von Superheld und Bat erbt
+class Batman(Superhero, Bat):
+
+ def __init__(self, *args, **kwargs):
+ # In der Regel müssen Sie super aufrufen, um Attribute zu erben:
+ # super (Batman, selbst) .__ init__ (* args, ** kwargs)
+ # Allerdings handelt es sich hier um Mehrfachvererbung, und super()
+ # funktioniert nur mit der nächsten Basisklasse in der MRO-Liste.
+ # Stattdessen rufen wir explizit __init__ für alle Vorfahren auf.
+ # Die Verwendung von *args und **kwargs ermöglicht die saubere Übergabe von
+ # Argumenten, wobei jedes übergeordnete Element eine Schicht der Zwiebel "abschält".
+ Superhero.__init__(self, 'anonymous', movie=True,
+ superpowers=['Wealthy'], *args, **kwargs)
+ Bat.__init__(self, *args, can_fly=False, **kwargs)
+ # überschreibt den Wert für das Namensattribut
+ self.name = 'Sad Affleck'
+
+ def sing(self):
+ return 'nan nan nan nan nan batman!'
+
+if __name__ == '__main__':
+ sup = Batman()
+
+ # Die Reihenfolge der Methodenauflösung (MRO = Method Resolution Order) anzeigen,
+ # die sowohl von getattr() als auch von super() verwendet wird.
+ # Dieses Attribut ist dynamisch und kann aktualisiert werden.
+ print(Batman.__mro__) # => (<class '__main__.Batman'>,
+ # => <class 'superhero.Superhero'>,
+ # => <class 'human.Human'>,
+ # => <class 'bat.Bat'>, <class 'object'>)
+
+ # Ruft die übergeordnete Methode auf, verwendet jedoch das eigene Klassenattribut
+ print(sup.get_species()) # => Superhuman
+
+ # Ruft die überschriebene Methode auf
+ print(sup.sing()) # => nan nan nan nan nan batman!
+
+ # Ruft die Methode von Human auf, weil die Reihenfolge der Vererbung wichtig ist
+ sup.say('I agree') # => Sad Affleck: I agree
+
+ # Aufrufmethode, die nur im 2. Vorfahren existiert
+ print(sup.sonar()) # => ))) ... (((
+
+ # Vererbtes Klassenattribut
+ sup.age = 100
+ print(sup.age) # => 100
+
+ # Vererbtes Attribut vom 2. Vorfahren, dessen Standardwert überschrieben wurde.
+ print('Can I fly? ' + str(sup.fly)) # => Can I fly? False
+
+
+####################################################
+## 7. Fortgeschrittenes
+####################################################
+
+# Generatoren helfen Ihnen, lazy Code zu erstellen.
+def double_numbers(iterable):
+ for i in iterable:
+ yield i + i
+
+# Generatoren sind speichereffizient, da sie nur die Daten laden,
+# die zur Verarbeitung des nächsten Werts in der iterierbaren Komponente
+# erforderlich sind. Dadurch können sie ansonsten unzulässig große Wertebereiche ausführen.
+# HINWEIS: `range` ersetzt` xrange` in Python 3.
+for i in double_numbers(range(1, 900000000)): # `range` ist ein Generator.
+ print(i)
+ if i >= 30:
+ break
+
+# Genauso wie Sie ein 'list comprehension' (Listen Abstraktion) erstellen können, können Sie auch 'generator comprehension' (Generator Abstraktion) erstellen.
+values = (-x for x in [1,2,3,4,5])
+for x in values:
+ print(x) # prints -1 -2 -3 -4 -5 to console/terminal
+
+# Sie können eine Generator Abstraktion auch direkt in eine Liste umwandeln (casten).
+values = (-x for x in [1,2,3,4,5])
+gen_to_list = list(values)
+print(gen_to_list) # => [-1, -2, -3, -4, -5]
+
+# Decorators
+# In diesem Beispiel umschliesst "beg" "say". Wenn say_please True ist, wird die zurückgegebene Nachricht geändert.
+from functools import wraps
+
+def beg(target_function):
+ @wraps(target_function)
+ def wrapper(*args, **kwargs):
+ msg, say_please = target_function(*args, **kwargs)
+ if say_please:
+ return "{} {}".format(msg, "Please! I am poor :(")
+ return msg
+
+ return wrapper
+
+@beg
+def say(say_please=False):
+ msg = "Can you buy me a beer?"
+ return msg, say_please
+
+
+print(say()) # Can you buy me a beer?
+print(say(say_please=True)) # Can you buy me a beer? Please! I am poor :(
+
+```
+
+## Lust auf mehr?
+
+### Kostenlos online (Englisch)
+
+* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/)
+* [Dive Into Python](http://www.diveintopython.net/)
+* [The Official Docs](http://docs.python.org/2.6/)
+* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/)
+* [Python Module of the Week](http://pymotw.com/2/)
+
+### Totholz (Englisch)
+
+* [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20)
+* [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20)
+* [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20)
+
diff --git a/de-de/qt-de.html.markdown b/de-de/qt-de.html.markdown
new file mode 100644
index 00000000..480030fe
--- /dev/null
+++ b/de-de/qt-de.html.markdown
@@ -0,0 +1,175 @@
+---
+category: tool
+tool: Qt Framework
+language: c++
+filename: learnqt-de.cpp
+contributors:
+ - ["Aleksey Kholovchuk", "https://github.com/vortexxx192"]
+translators:
+ - ["Dennis Keller", "https://github.com/denniskeller"]
+lang: de-de
+---
+
+**Qt** ist ein weithin bekanntes Framework zum Entwickeln von cross-platform Software,
+die auf verschiedenen Hard- und Softwareplatformen mit wenig oder keinen Veränderungen im Code läuft.
+Dabei besitzt man die Power und Geschiwindigkeit von nativen Anwendungen.
+Obwohl **Qt** ursprünglich in *C++* geschrieben wurde,
+gibt es verschiedene Ports für andere Sprachen: *[PyQt](https://learnxinyminutes.com/docs/pyqt/)*, *QtRuby*, *PHP-Qt*, etc.
+
+**Qt** eignet sich hervorragend zum Erstellen von Anwendungen mit grafischer Benutzeroberfläche (GUI).
+Dieses Tutorial zeigt, wie man das in *C++* macht.
+
+```c++
+/*
+ * Lass uns klassisch starten
+ */
+
+// Alle Header vom Qt Framework starten mit dem Großbuchstaben 'Q'.
+#include <QApplication>
+#include <QLineEdit>
+
+int main(int argc, char *argv[]) {
+ // Erstellt ein Objekt um applikationsweit die Resourcen zu managen.
+ QApplication app(argc, argv);
+
+ // Erstellt ein Line edit Widget und zeigt es auf dem Bildschirm
+ QLineEdit lineEdit("Hello world!");
+ lineEdit.show();
+
+ // Startet die Event Loop der Anwendung.
+ return app.exec();
+}
+```
+
+Die GUI bezogene Teile von **Qt** bestehen aus *Widgets* und den *Verbindungen*
+dazwischen.
+
+[Lies mehr über Widgets](http://doc.qt.io/qt-5/qtwidgets-index.html)
+
+```c++
+/*
+ * Lass uns Label und einen Button machen.
+ * Ein Label soll auftauchen, wenn der Button gedrückt wird.
+ *
+ * Der Qt Code spricht für sich selbst.
+ */
+
+#include <QApplication>
+#include <QDialog>
+#include <QVBoxLayout>
+#include <QPushButton>
+#include <QLabel>
+
+int main(int argc, char *argv[]) {
+ QApplication app(argc, argv);
+
+ QDialog dialogWindow;
+ dialogWindow.show();
+
+ // Füge ein vertikales Layout hinzu
+ QVBoxLayout layout;
+ dialogWindow.setLayout(&layout);
+
+ QLabel textLabel("Danke für das Knopf drücken");
+ layout.addWidget(&textLabel);
+ textLabel.hide();
+
+ QPushButton button("Drück mich");
+ layout.addWidget(&button);
+
+ // Zeigt verstecktes Label, wenn der Button gedrückt wird.
+ QObject::connect(&button, &QPushButton::pressed,
+ &textLabel, &QLabel::show);
+
+ return app.exec();
+}
+```
+
+Beachte den *QObject::connect* Teil. Diese Methode wird verwendet,
+um *Signale* eines Objekts mit den *Slots* eines Objektes zu verbinden.
+
+**Signale** werden ausgegeben, wenn bestimmte Dinge mit Objekten passieren.
+Beispielsweise wird das *pressed* Signal ausgegeben,
+wenn der Benutzer auf das QPushButton Objekt drückt.
+
+**Slots** sind Aktionen, die als Reaktion auf empfangene Signale ausgeführt werden können.
+
+[Lies mehr über Slots und Signale](http://doc.qt.io/qt-5/signalsandslots.html)
+
+
+Als Nächstes lernen wir, dass wir nicht nur Standard Widgets verwenden können,
+sondern auch ihr Verhalten mithilfe von Vererbung verändern können.
+Lass uns einen Button erschaffen, der zählt, wie häufig er gedrückt wird.
+Dafür definieren wir unsere eigene Klasse *CounterLabel*.
+Diese muss wegen der speziellen Qt Architektur in einer seperaten Datei deklariert werden.
+
+```c++
+// counterlabel.hpp
+
+#ifndef COUNTERLABEL
+#define COUNTERLABEL
+
+#include <QLabel>
+
+class CounterLabel : public QLabel {
+ Q_OBJECT // Qt definiertes Makro, welches in jedem modifizierten Widget vorhanden sein muss.
+
+public:
+ CounterLabel() : counter(0) {
+ setText("Zähler wurde noch nicht erhöht."); // Methode von QLabel
+ }
+
+public slots:
+ // Aktion, die ausgeführt wird, wenn der Button gedrückt wird.
+ void increaseCounter() {
+ setText(QString("Zähler Wert: %1").arg(QString::number(++counter)));
+ }
+
+private:
+ int counter;
+};
+
+#endif // Zähllabel
+```
+
+```c++
+// main.cpp
+// Fast das Gleiche, wie das vorherige Beispiel
+
+#include <QApplication>
+#include <QDialog>
+#include <QVBoxLayout>
+#include <QPushButton>
+#include <QString>
+#include "counterlabel.hpp"
+
+int main(int argc, char *argv[]) {
+ QApplication app(argc, argv);
+
+ QDialog dialogWindow;
+ dialogWindow.show();
+
+ QVBoxLayout layout;
+ dialogWindow.setLayout(&layout);
+
+ CounterLabel counterLabel;
+ layout.addWidget(&counterLabel);
+
+ QPushButton button("Drück mich nochmal.");
+ layout.addWidget(&button);
+ QObject::connect(&button, &QPushButton::pressed,
+ &counterLabel, &CounterLabel::increaseCounter);
+
+ return app.exec();
+}
+```
+
+Das wars! Natürlich ist das Qt Framework erheblich größer, als der der Teil der in diesem Tutorial behandelt wurde.
+Das heißt, es gibt viel zu lesen und zu üben.
+
+## Further reading
+
+- [Qt 4.8 tutorials](http://doc.qt.io/qt-4.8/tutorials.html)
+- [Qt 5 tutorials](http://doc.qt.io/qt-5/qtexamplesandtutorials.html)
+
+Viel Erfolg und viel Spaß!
diff --git a/de-de/rst-de.html.markdown b/de-de/rst-de.html.markdown
new file mode 100644
index 00000000..072299f5
--- /dev/null
+++ b/de-de/rst-de.html.markdown
@@ -0,0 +1,119 @@
+---
+language: restructured text (RST)
+filename: restructuredtext-de.rst
+contributors:
+ - ["DamienVGN", "https://github.com/martin-damien"]
+ - ["Andre Polykanine", "https://github.com/Oire"]
+translators:
+ - ["Dennis Keller", "https://github.com/denniskeller"]
+lang: de-de
+---
+
+RST ist ein Dateiformat, das von der Python Community entwickelt wurde,
+
+um Dokumentation zu schreiben (und ist somit Teil von Docutils).
+
+RST-Dateien sind simple Textdateien mit einer leichtgewichtigen Syntax (im Vergleich zu HTML).
+
+
+## Installation
+
+Um Restructured Text zu vewenden musst du [Python](http://www.python.org)
+
+installieren und das `docutils` Packet installieren. `docutils` kann mit dem folgenden
+
+Befehl auf der Kommandozeile installiert werden:
+
+```bash
+$ easy_install docutils
+```
+
+Wenn auf deinem System `pip` installiert kannst du es statdessen auch verwenden:
+
+```bash
+$ pip install docutils
+```
+
+
+## Dateisyntax
+
+Ein einfaches Beispiel für die Dateisyntax:
+
+```
+.. Zeilen, die mit zwei Punkten starten sind spezielle Befehle.
+
+.. Wenn kein Befehl gefunden wird, wird die Zeile als Kommentar gewertet.
+
+============================================================================
+Haupttitel werden mit Gleichheitszeichen darüber und darunter gekennzeichnet
+============================================================================
+
+Beachte das es genau so viele Gleichheitszeichen, wie Hauptitelzeichen
+geben muss.
+
+Titel werden auch mit Gleichheitszeichen unterstrichen
+======================================================
+
+Untertitel werden mit Strichen gekennzeichnet
+---------------------------------------------
+
+Text in *kursiv* oder in **fett**. Du kannst Text als Code "makieren", wenn
+du doppelte Backquotes verwendest ``: ``print()``.
+
+Listen sind so einfach wie in Markdown:
+
+- Erstes Element
+- Zweites Element
+ - Unterelement
+
+oder
+
+* Erstes Element
+* Zweites Element
+ * Unterelement
+
+Tabellen sind einfach zu schreiben:
+
+=========== ==========
+Land Hauptstadt
+=========== ==========
+Frankreich Paris
+Japan Tokyo
+=========== ========
+
+Komplexere Tabellen (zusammengeführte Spalten und Zeilen) können einfach
+erstellt werden, aber ich empfehle dir dafür die komplette Dokumentation zu lesen :)
+
+Es gibt mehrere Möglichkeiten um Links zu machen:
+
+- Wenn man einen Unterstrich hinter einem Wort hinzufügt: Github_ Zusätzlich
+muss man die Zielurl nach dem Text hinzufügen.
+(Dies hat den Vorteil, dass man keine unnötigen Urls in lesbaren Text einfügt.
+- Wenn man die vollständige Url eingibt : https://github.com/
+(Dies wird automatisch in ein Link konvertiert.)
+- Wenn man es mehr Markdown ähnlich eingibt: `Github <https://github.com/>`_ .
+
+.. _Github https://github.com/
+
+```
+
+
+## Wie man es verwendet
+
+RST kommt mit docutils, dort hast du den Befehl `rst2html`, zum Beispiel:
+
+```bash
+$ rst2html myfile.rst output.html
+```
+
+*Anmerkung : Auf manchen Systemen könnte es rst2html.py sein*
+
+Es gibt komplexere Anwendungen, die das RST Format verwenden:
+
+- [Pelican](http://blog.getpelican.com/), ein statischer Websitengenerator
+- [Sphinx](http://sphinx-doc.org/), Ein Dokumentationsgenerator
+- und viele Andere
+
+## Zum Lesen
+
+- [Offizielle Schnellreferenz](http://docutils.sourceforge.net/docs/user/rst/quickref.html)
diff --git a/de-de/ruby-de.html.markdown b/de-de/ruby-de.html.markdown
index e14603cd..8025a8c0 100644
--- a/de-de/ruby-de.html.markdown
+++ b/de-de/ruby-de.html.markdown
@@ -1,5 +1,6 @@
---
language: ruby
+filename: ruby-de.rb
contributors:
- ["David Underwood", "http://theflyingdeveloper.com"]
- ["Joel Walden", "http://joelwalden.net"]
@@ -11,602 +12,677 @@ contributors:
- ["Dzianis Dashkevich", "https://github.com/dskecse"]
- ["Levi Bostian", "https://github.com/levibostian"]
- ["Rahil Momin", "https://github.com/iamrahil"]
+ - ["Gabriel Halley", "https://github.com/ghalley"]
+ - ["Persa Zula", "http://persazula.com"]
+ - ["Jake Faris", "https://github.com/farisj"]
+ - ["Corey Ward", "https://github.com/coreyward"]
+ - ["Jannik Siebert", "https://github.com/janniks"]
+ - ["Keith Miyake", "https://github.com/kaymmm"]
translators:
- ["Christian Albrecht", "https://github.com/coastalchief"]
- ["Dennis Keller", "https://github.com/denniskeller"]
-filename: ruby-de.rb
+ - ["Paul Götze", "https://gitub.com/paulgoetze"]
lang: de-de
---
-# Dies ist ein Kommentar
+```ruby
+# Das ist ein Kommentar
=begin
-Dies sind multi-line
-Kommentare. Niemand benutzt
-die wirklich.
+Das ist ein mehrzeiliger Kommentar.
+Die Anfangszeile muss mit "=begin" beginnen
+und die Endzeile muss mit "=end" beginnen.
+
+Alternativ kannst du jede Zeile in einem
+mehrzeiligen Kommentar mit dem # Zeichen beginnen.
=end
-# Objekte - Alles ist ein Objekt
+# In Ruby ist (fast) alles ein Objekt.
+# Das schließt Zahlen ein...
+3.class #=> Integer
-## Zahlen sind Objekte
-```
-3.class #=> Fixnum
-3.to_s #=> "3"
-```
+# ...und Zeichenketten (Strings)...
+"Hallo".class #=> String
-### Simple Arithmetik
-```
+# ...und sogar Methoden!
+"Hallo".method(:class).class #=> Method
+
+# Simple Arithmetik
1 + 1 #=> 2
8 - 1 #=> 7
10 * 2 #=> 20
35 / 5 #=> 7
-2**5 #=> 32
-```
+2 ** 5 #=> 32
+5 % 3 #=> 2
-// Arithmetik ist aber eigentlich nur syntaktischer Zucker
-// um eine Methode eines Objekt aufzurufen
-```
+# Bitweise Operatoren
+3 & 5 #=> 1
+3 | 5 #=> 7
+3 ^ 5 #=> 6
+
+# Arithmetik ist aber eigentlich nur syntaktischer Zucker
+# um eine Methode eines Objekts aufzurufen
1.+(3) #=> 4
10.* 5 #=> 50
-```
+100.methods.include?(:/) #=> true
-## Special values sind Objekte
-```
-nil # Nothing to see here
-true # truth
-false # falsehood
+## Spezielle Werte sind Objekte
+nil # Equivalent zu null in anderen Sprachen
+true # Wahrheitswert
+false # Falschheitswert
nil.class #=> NilClass
true.class #=> TrueClass
false.class #=> FalseClass
-```
-## Objektvergleiche
-### Gleicheit
-```
+# Gleicheit
1 == 1 #=> true
2 == 1 #=> false
-```
-### Ungleichheit
-```
+
+# Ungleichheit
1 != 1 #=> false
2 != 1 #=> true
-```
-### Neben false selbst, nil ist ein anderer 'falsey' Wert
-```
-!nil #=> true
-!false #=> true
-!0 #=> false
-```
-### Weitere Vergleiche
-```
+
+# Neben false selbst, ist nil der einzige andere
+# zu Falsch evaluierende Wert
+
+!!nil #=> false
+!!false #=> false
+!!0 #=> true
+!!"" #=> true
+
+# Weitere Vergleiche
1 < 10 #=> true
1 > 10 #=> false
2 <= 2 #=> true
2 >= 2 #=> true
-```
+
+# Kombinierter Vergleichsoperator (gibt `1` zurück wenn das erste Argument
+# größer ist, und `-1`, wenn das zweite Argument größer ist, sonst `0`)
+1 <=> 10 #=> -1 (1 < 10)
+10 <=> 1 #=> 1 (10 > 1)
+1 <=> 1 #=> 0 (1 == 1)
+
### Logische Operatoren
-```
true && false #=> false
true || false #=> true
-!true #=> false
-```
-Es gibt alternative Versionen der logischen Operatoren mit niedrigerer
-Wertigkeit. Diese werden meistens bei Flow-Control eingesetzt, um
-verschiedenen Ausdrücke zu verketten bis einer true oder false zurück
-liefert.
+# Es gibt alternative Versionen der logischen Operatoren mit niedrigerer
+# Wertigkeit. Diese werden meistens zur Flusskontrolle eingesetzt, um
+# verschiedenen Ausdrücke zu verketten bis einer true oder false zurück
+# liefert.
-#### and
-##### `do_something_else` wird nur ausgewertet wenn `do_something` true ist.
+# `do_something_else` wird nur ausgewertet wenn `do_something` true ist.
do_something() and do_something_else()
-
-#### or
-#####`log_error` wird nur ausgewertet wenn `do_something` false ist.
+# `log_error` wird nur ausgewertet wenn `do_something` false ist.
do_something() or log_error()
-## Strings sind Objekte
-```
-'I am a string'.class #=> String
-"I am a string too".class #=> String
+# String Interpolation
+placeholder = 'Ruby'
+"Ich kann in #{placeholder} Platzhalter mit doppelten Anführungszeichen füllen."
+#=> "Ich kann in Ruby Platzhalter mit doppelten Anführungszeichen füllen."
-platzhalter = 'Ruby'
-"Ich kann in #{placeholder} Platzhalter mit doppelten Anführungsstrichen füllen."
-```
-Einfache Anführungszeichen sollten bevorzugt werden.
-Doppelte Anführungszeichen führen interne Berechnungen durch.
+# Du kannst Strings mit `+` verbinden, nicht jedoch mit anderen Typen
+'hallo ' + 'Welt' #=> "hallo Welt"
+'Hallo ' + 3 #=> TypeError: no implicit conversion of Integer into String
+'hallo ' + 3.to_s #=> "hallo 3"
+"hallo #{3}" #=> "hallo 3"
+
+# ...oder Strings mit Operatoren kombinieren
+'hallo ' * 3 #=> "hallo hallo hallo "
+
+# ...oder Strings an andere Strings anhängen
+'hallo' << ' Welt' #=> "hallo Welt"
+
+# Du kannst Text mit einer neuen Zeile am Ende ausgeben
+puts "Ich gebe Text aus!"
+#=> Ich gebe Text aus!
+#=> nil
+
+# ...oder Text ohne einen Zeilenumbruch ausgeben
+print "Ich gebe Text aus!"
+#=> "Ich gebe Text aus!" => nil
-### Strings können verbunden werden, aber nicht mit Zahlen
-```
-'hello ' + 'world' #=> "hello world"
-'hello ' + 3 #=> TypeError: can't convert Fixnum into String
-```
-#### Zahl muss in String konvertiert werden
-```
-'hello ' + 3.to_s #=> "hello 3"
-```
-### Text ausgeben
-```
-puts "I'm printing!"
-```
# Variablen
-## Zuweisungen
-### Diese Zuweisung gibt den zugeordneten Wert zurück
-```
x = 25 #=> 25
x #=> 25
-```
-### Damit funktionieren auch mehrfache Zuweisungen
-```
+
+# Beachte, dass Zuweisungen den zugewiesenen Wert zurückgeben.
+# D.h. du kannst mehrfache Zuweisungen machen.
+
x = y = 10 #=> 10
x #=> 10
y #=> 10
-```
-## Benennung
-### Konvention ist snake_case
-```
+
+# Nutze snake_case für Variablennamen.
snake_case = true
-```
-### Benutze verständliche Variablennamen
-```
-path_to_project_root = '/good/name/'
-path = '/bad/name/'
-```
-# Symbols (sind auch Objekte)
-Symbols sind unveränderliche, wiederverwendbare Konstanten, welche intern
-als integer repräsentiert werden. Sie werden häufig anstelle von Strings
-verwendet, um sinnvoll Werte zu übermitteln.
-Symbols werden mit dem Doppelpunkt gekennzeichnet.
-```
+# Nutze verständliche Variablennamen.
+path_to_project_root = '/guter/Name/'
+m = '/schlechter/Name/'
+
+
+# Symbole sind unveränderliche, wiederverwendbare Konstanten, welche intern
+# als Integer repräsentiert werden. Sie werden häufig anstelle von Strings
+# verwendet, um semantisch sinnvoll Werte zu übermitteln.
+# Symbols werden mit dem Doppelpunkt gekennzeichnet.
+
:pending.class #=> Symbol
+
status = :pending
+
status == :pending #=> true
+
status == 'pending' #=> false
+
status == :approved #=> false
-```
+
+# Strings können in Symbole konvertiert werden und umgekehrt.
+status.to_s #=> "pending"
+"argon".to_sym #=> :argon
+
# Arrays
-## Ein Array anlegen
-```
+# Das ist ein Array.
array = [1, 2, 3, 4, 5] #=> [1, 2, 3, 4, 5]
-```
-## Array können verschiedene Typen beinhalten
-```
+# Array können verschiedene Typen beinhalten
[1, 'hello', false] #=> [1, "hello", false]
-```
-## Wie bei arithmetischen Ausdrücken auch wird beim Zugriff auf
-## [0] eigentlich die Methode [] des Array Objekts aufgerufen.
-```
-array.[] 0 #=> 1
-array.[] 12 #=> nil
-```
+## Arrays könnenindiziert werden.
-## Arrays können von vorne indiziert werden
-```
+# Von vorne...
array[0] #=> 1
+array.first #=> 1
array[12] #=> nil
-```
-## Arrays können von hinten indiziert werden
-```
+# ...oder von hinten...
array[-1] #=> 5
-```
+array.last #=> 5
-## Arrays können mit Start Index und Länge indiziert werden
-```
+# ...oder mit einem Startindex und einer Länge...
array[2, 3] #=> [3, 4, 5]
-```
-## Arrays können mit einer Range indiziert werden
-```
+# ...oder mit einem Range...
array[1..3] #=> [2, 3, 4]
-```
-## Einen Wert hinzufügen
-```
+# Du kanns ein Array umkehren.
+# Gib ein neues Array mit umgkehrten Werten zurück
+[1,2,3].reverse #=> [3,2,1]
+
+# Kehre ein Array an Ort und Stelle um, um die Variable mit den
+# umgekehrten Werten zu aktualisieren.
+a = [1,2,3]
+a.reverse! #=> a==[3,2,1] wegen des Aufrufs von reverse mit Ausrufezeichens ('!')
+
+# Wie bei der Arithmetik, ist Zugriff mit [index] nur
+# syntaktischer Zucker für den Aufruf der `[]` Methode auf dem Objekt.
+array.[] 0 #=> 1
+array.[] 12 #=> nil
+
+# Du kannst Werte zu einem Array hinzufügen...
array << 6 #=> [1, 2, 3, 4, 5, 6]
+# Oder so
array.push(6) #=> [1, 2, 3, 4, 5, 6]
-```
-## Testen, ob ein Element schon vorhanden ist
-```
+# ...und testen ob ein Element schon vorhanden ist
array.include?(1) #=> true
-```
-# Hashes
-Hashes sind das Hauptfeature um Key/Values zu speichern
+# Hashes sind Rubys Hauptdatenstruktur for Schlüssel/Wert Paare.
+# Hashes werden durch geschweifte Klammern gekennzeichnet.
+hash = { 'Farbe' => 'grün', 'Nummer' => 5 }
-## Ein Hash anlegen
-```
-hash = { 'color' => 'green', 'number' => 5 }
-hash.keys #=> ['color', 'number']
-```
+hash.keys #=> ['farbe', 'nummer']
-## Wert per key herausfinden
-```
-hash['color'] #=> 'green'
-hash['number'] #=> 5
-hash['nothing here'] #=> nil
-// Fragen an einen Hash nach einem Schlüssel, der nicht existiert, ruft nil hervor:
-```
+# Hashes can be quickly looked up by key.
+hash['Farbe'] #=> "grün"
+hash['Nummer'] #=> 5
-## Symbols können auch keys sein
-```
-new_hash = { defcon: 3, action: true }
-new_hash.keys #=> [:defcon, :action]
-```
+# Abfragen eines nicht vorhandenen Schlüssels, gibt nil zurück.
+hash['nicht vorhanden'] #=> nil
-## Testen ob ein Key oder ein Value existiert
-```
-new_hash.has_key?(:defcon) #=> true
-new_hash.has_value?(3) #=> true
-```
+# Wenn du Symbole als Schlüssel in einem Hash verwendest, kannst du
+# eine alternative Syntax verwenden.
+hash = { :defcon => 3, :action => true }
+hash.keys #=> [:defcon, :action]
-### Tipp: Arrays und Hashes sind Enumerable
-### Und haben gemeinsame, hilfreiche Methoden wie:
-### each, map, count, and more
+hash = { defcon: 3, action: true }
+hash.keys #=> [:defcon, :action]
+
+# Testen ob ein Schlüssel oder Wert im Hash existiert
+hash.key?(:defcon) #=> true
+hash.value?(3) #=> true
+
+# Tipp: Arrays und Hashes sind Enumerables!
+# Sie haben viele nützliche Methoden gemein, wie each, map, count, und andere.
# Kontrolstrukturen
-## if
-```
+
+# Bedingungen
if true
- 'if statement'
+ 'wenn Bedingung'
elsif false
- 'else if, optional'
+ 'sonst wenn, optional'
else
- 'else, also optional'
+ 'sonst, auch optional'
end
-```
-## for - Allerdings werden for Schleifen nicht oft vewendet.
-```
-for counter in 1..5
- puts "iteration #{counter}"
-end
-```
-## Stattdessen: "each" Methode und einen Bloch übergeben
-Ein Block ist ein Codeteil, den man einer Methode übergeben kann
-Ähnelt stark lambdas, anonymen Funktionen oder Closures in anderen
-Programmiersprachen.
-```
+# Wenn eine Kontrollstruktur keinen Code-Block, sondern einen einzigen
+# Ausdruck ausführt, dann kannst du die nachgestellte if-Notation verwenden
+warnings = ['Nachname fehlt', 'Adresse zu kurz']
+puts("Vorhandene Warnungen:\n" + warnings.join("\n")) if !warnings.empty?
+
+# Formuliere die Bedingung um, wenn sich `unless` besser liest als `if`
+puts("Vorhandene Warnungen:\n" + warnings.join("\n")) unless warnings.empty?
+
+# Schleifen
+# Traditionell ist das Benutzen von `for` Schleifen in Ruby eher unüblich.
+# Stattdessen werden diese mit Hilfe von Enumerables implementiert, was mit
+# dem Aufrufen von `each` einhergeht.
(1..5).each do |counter|
- puts "iteration #{counter}"
+ puts "Iteration #{counter}"
+end
+
+# Was in etwa das selbe ist wie Folgendes (selten in Ruby zu sehen).
+for counter in 1..5
+ puts "Iteration #{counter}"
end
-```
-Die each Methode einer Range führt den Block für jedes Element der Range aus.
+# Das `do |variable| ... end` Konstrukt wird `block` genannt.
+# Blocks sind vergleichbar mit Lambdas, anonymen Funktionen
+# oder Closures in anderen Programmiersprachen.
+# Sie können als Objekte übergeben, aufgerufen oder als Methoden
+# zugewiesen werden.
-Dem Block wird ein "counter" parameter übergeben.
+# Die `each` Methode eines Ranges führt den Block einmal für jedes
+# Element des Ranges aus.
+# Dem Block wird eine counter Variable als Parameter übergeben.
-### Den Block kann man auch in geschweiften Klammern schreiben
-```
-(1..5).each { |counter| puts "iteration #{counter}" }
-```
+# Du kannst einen Block auch mit geschweiften Klammern schreiben.
+(1..5).each { |counter| puts "Iteration #{counter}" }
-### Each kann auch über den Inhalt von Datenstrukturen iterieren
-```
+# Each kann auch über den Inhalt von Datenstrukturen iterieren.
array.each do |element|
- puts "#{element} is part of the array"
+ puts "#{element} is Teil des Arrays"
end
+
hash.each do |key, value|
- puts "#{key} is #{value}"
+ puts "#{key} ist #{value}"
+end
+
+# Um auf den Laufindex zuzugreifen kannst du `each_with_index` verwenden
+# und eine index Variable definieren.
+array.each_with_index do |element, index|
+ puts "#{element} ist Nummer #{index} im Array"
end
counter = 1
while counter <= 5 do
- puts "iteration #{counter}"
+ puts "Iteration #{counter}"
counter += 1
end
-```
+#=> Iteration 1
+#=> Iteration 2
+#=> Iteration 3
+#=> Iteration 4
+#=> Iteration 5
+
+# Es gibt einige andere hilfreiche Schleifenfunktionen in Ruby.
+# Wie etwa 'map', 'reduce', 'inject' und viele andere mehr.
+# Map zum Beispiel iteriert über das Array, führt für jedes Element
+# die Anweisungen aus,
+# die im Block definiert sind und gibt ein völlig neues Array zurück.
+array = [1,2,3,4,5]
+doubled = array.map do |element|
+ element * 2
+end
+puts doubled
+#=> [2,4,6,8,10]
+puts array
+#=> [1,2,3,4,5]
-## case
-```
+# Case Konstruct
grade = 'B'
case grade
when 'A'
- puts 'Way to go kiddo'
+ puts 'So wird’s gemacht'
when 'B'
- puts 'Better luck next time'
+ puts 'Viel Glück beim nächsten Mal'
when 'C'
- puts 'You can do better'
+ puts 'Das kannst du besser'
when 'D'
- puts 'Scraping through'
+ puts 'Gerade so durch'
when 'F'
- puts 'You failed!'
+ puts 'Durchgefallen!'
else
- puts 'Alternative grading system, eh?'
+ puts 'Anderes Bewertungssystem, was?'
end
-=> "Better luck next time"
-```
+#=> "Viel Glück beim nächsten Mal"
-### Case können auch ranges
-```
+# Case kann auch Ranges benutzen
grade = 82
case grade
when 90..100
- puts 'Hooray!'
+ puts 'Hurra!'
when 80...90
- puts 'OK job'
+ puts 'OK gemacht'
else
- puts 'You failed!'
+ puts 'Durchgefallen!'
end
-=> "OK job"
-```
+#=> "OK gemacht"
-# Exception handling:
-```
+# Fehlerbehandlung
begin
- # code here that might raise an exception
- raise NoMemoryError, 'You ran out of memory.'
+ # Code der einen Fehler wirft...
+ raise NoMemoryError, 'Dein Speicher ist voll.'
rescue NoMemoryError => exception_variable
- puts 'NoMemoryError was raised', exception_variable
+ puts 'NoMemoryError ist aufgetreten', exception_variable
rescue RuntimeError => other_exception_variable
- puts 'RuntimeError was raised now'
+ puts 'RuntimeError ist aufgetreten'
else
- puts 'This runs if no exceptions were thrown at all'
+ puts 'Das wird ausgeführt, wenn keine Fehler geworfen wurden'
ensure
- puts 'This code always runs no matter what'
+ puts 'Dieser Code wird immer ausgeführt, egal was vorher passiert'
end
-```
-# Funktionen
-```
+
+# Methoden
+
def double(x)
x * 2
end
-```
-## Funktionen (und Blocks)
-## geben implizit den Wert des letzten Statements zurück
-```
+
+# Methoden (und Blocks) geben implizit den Wert des letzten Anweisung zurück.
double(2) #=> 4
-```
-### Klammern sind optional wenn das Ergebnis nicht mehrdeutig ist
-```
+# Klammern sind optional wenn die Anweisung dadurch nicht mehrdeutig wird.
double 3 #=> 6
+
double double 3 #=> 12
+
def sum(x, y)
x + y
end
-```
-### Methoden Parameter werden per Komma getrennt
-```
+# Die Argumente einer Methode werden durch ein Komma getrennt.
sum 3, 4 #=> 7
+
sum sum(3, 4), 5 #=> 12
-```
-## yield
-### Alle Methoden haben einen impliziten, optionalen block Parameter
-### Dieser wird mit dem Schlüsselword "yield" aufgerufen
-```
+# yield
+# Alle Methoden haben implizit einen optionalen block Parameter.
+# Dieser kann durch das Schlüsselwort 'yield' ausgeführt werden.
def surround
puts '{'
yield
puts '}'
end
-surround { puts 'hello world' }
-```
-## Einen Block kann man auch einer Methoden übergeben
-### "&" kennzeichnet die Referenz zum übergebenen Block
-```
+surround { puts 'hallo Welt' }
+
+#=> {
+#=> hallo Welt
+#=> }
+
+# Blocks können in ein 'Proc' Objekt umgewandelt werden.
+# Dieses ist eine Art Container um den Block und erlaubt ihn an eine
+# andere Methode zu übergeben, ihn in einen anderen Gültigkeitsbereicht
+# einzubinden oder ihn andersweitig zu verändern.
+# Am häufigsten findet man dies bei Parameterlisten von Methoden, in Form
+# eines letzten '&block' Parameters, der den Block – wenn es einen gibt –
+# entgegen nimmt und ihn in ein 'Proc' umwandelt. Die Benennung '&block' ist
+# hier nur eine Konvention; es würde genauso mit '&pineapple' funktionieren.
def guests(&block)
- block.call 'some_argument'
+ block.class #=> Proc
+ block.call(4)
end
-```
-### Eine Liste von Parametern kann man auch übergeben,
-### Diese wird in ein Array konvertiert
-### "*" kennzeichnet dies.
-```
+# Die 'call' Methode eines Proc ist ganz ähnlich zum Aufruf von 'yield', wenn
+# ein Block vorhanden ist. Die Argumente, die 'call' übergeben werden, werden
+# als Argumente and den Block weitergereicht.
+
+guests { |n| "Du hast #{n} Gäste." }
+# => "Du hast 4 Gäste."
+
+# Du kannst eine Liste von Argumenten übergeben, die dann in ein Array
+# umgewandelt werden. Dafür gibt es den splat-Operator (`*`).
def guests(*array)
array.each { |guest| puts guest }
end
-```
+
+# Destrukturierung
+
+# Ruby destrukturiert Arrays automatisch beim Zuweisen mehrerer Variablen.
+a, b, c = [1, 2, 3]
+a #=> 1
+b #=> 2
+c #=> 3
+
+# In manchen Fällen will man den splat-Operator (`*`) verwenden um ein Array in
+# eine Liste zu destrukturieren.
+ranked_competitors = ["John", "Sally", "Dingus", "Moe", "Marcy"]
+
+def best(first, second, third)
+ puts "Gewinner sind #{first}, #{second} und #{third}."
+end
+
+best *ranked_competitors.first(3) #=> Gewinner sind John, Sally and Dingus.
+
+# Der splat-Operator kann auch in Parametern verwendet werden.
+def best(first, second, third, *others)
+ puts "Gewinner sind #{first}, #{second} und #{third}."
+ puts "Es gab #{others.count} andere Teilnehmer."
+end
+
+best *ranked_competitors
+#=> Gewinner sind John, Sally und Dingus.
+#=> Es gab 2 andere Teilnehmer.
+
+# Per Konvention enden alle Methoden, die einen Wahrheitswert zurück geben, mit einem
+# Fragezeichen.
+5.even? #=> false
+5.odd? #=> true
+
+# Wenn ein Methodenname mit einem Ausrufezeichen endet, dann tut diese Methode
+# per Konvention etwas Destruktives, wie z.B. das aufrufende Objekt zu
+# verändern.
+# Viele Mehtoden haben eine !-Version um eine direkte Änderung zu machen und
+# eine Nicht-!-Version, die ein neues Objekt mit den Veränderungen zurück gibt.
+company_name = "Dunder Mifflin"
+company_name.upcase #=> "DUNDER MIFFLIN"
+company_name #=> "Dunder Mifflin"
+# Diesmal verändern wir company_name direkt.
+company_name.upcase! #=> "DUNDER MIFFLIN"
+company_name #=> "DUNDER MIFFLIN"
+
# Klassen
-## Werden mit dem class Schlüsselwort definiert
-```
+
+# Du kannst eine Klasse mit dem Schlüsselwort 'class' definieren.
class Human
-```
-### Konstruktor bzw. Initializer
-```
+ # Eine Klassenvariable. Sie wird von allen Instanzen einer Klasse geteilt.
+ @@species = 'H. sapiens'
+
+ # Konstruktor bzw. Initializer
def initialize(name, age = 0)
- # Assign the argument to the "name" instance variable for the instance
+ # Weise das Argument der Instanzvariable 'name' zu.
@name = name
- # If no age given, we will fall back to the default in the arguments list.
+ # Wenn kein 'age' angegeben wurde wird der Standartwert aus der Argumentenlist verwendet.
@age = age
end
-```
-### setter Methode
-```
+ # Setter Methode
def name=(name)
@name = name
end
-```
-### getter Methode
-```
+
+ # Getter Methode
def name
@name
end
-```
-#### getter können mit der attr_accessor Methode vereinfacht definiert werden
-```
+ # Getter & Setter können auch kürzer mit der attr_accessor Methode erstellt werden.
attr_accessor :name
- # Getter/setter methods can also be created individually like this
+
+ # Getter & Setter Methoden können auch einzeln erstellt werden.
attr_reader :name
attr_writer :name
- # A class method uses self to distinguish from instance methods.
- # It can only be called on the class, not an instance.
+
+ # Eine Klassenmethode unterscheidet sich durch ein 'self' von einer
+ # Instanzmethode.
+ # Sie kann nur auf der Klasse und nicht auf einer Instanz der Klasse
+ # aufgerufen werden.
def self.say(msg)
puts msg
end
+
def species
@@species
end
end
-```
-## Eine Klasse instanziieren
-```
+# Instanziieren einer Klasse
jim = Human.new('Jim Halpert')
dwight = Human.new('Dwight K. Schrute')
-```
-## Methodenaufrufe
-```
+# Du kannst die Methoden des erstellten Objekts aufrufen.
jim.species #=> "H. sapiens"
jim.name #=> "Jim Halpert"
jim.name = "Jim Halpert II" #=> "Jim Halpert II"
jim.name #=> "Jim Halpert II"
dwight.species #=> "H. sapiens"
dwight.name #=> "Dwight K. Schrute"
-```
-## Eine Klassenmethode aufrufen
-```
+# Aufrufen einer Klassenmethode
Human.say('Hi') #=> "Hi"
-```
-## Variable Gültigkeit
-### Variablen die mit "$" starten, gelten global
-```
-$var = "I'm a global var"
+# Der Gültigkeitsbereich einer Variablen wird durch ihren Namen definiert.
+# Variablen, die mit $ beginnen sind global gültig.
+$var = "Ich bin eine globale Variable"
defined? $var #=> "global-variable"
-```
-### Variablen die mit "@" starten, gelten für die Instanz
-```
-@var = "I'm an instance var"
+# Variablen, die mit @ beginnen, sind innerhalb einer Instanz gültig.
+@var = "Ich bin eine Instanzvariable"
defined? @var #=> "instance-variable"
-```
-### Variablen die mit "@@" starten, gelten für die Klasse
-```
-@@var = "I'm a class var"
+# Variablen, die mit @@ beginnen, sind für die Klasse gültig.
+@@var = "Ich bin eine Klassenvariable"
defined? @@var #=> "class variable"
-```
-### Variablen die mit einem Großbuchstaben anfangen, sind Konstanten
-```
-Var = "I'm a constant"
+# Variablen, die mit einem Großbuchstaben beginnen, sind Konstanten
+Var = "Ich bin eine Konstante"
defined? Var #=> "constant"
-```
-## Class ist auch ein Objekt
-### Hat also auch Instanzvariablen
-### Eine Klassenvariable wird innerhalb der Klasse und Ableitungen geteilt.
+# Class ist in Ruby auch ein Objekt. Deshalb kann eine Klasse Instanzvariablen
+# haben. Eine Klassenvariable wird zwischen der Klasse und all ihren
+# Ableitungen geteilt.
-### Basis Klasse
-```
+# Basis Klasse
class Human
@@foo = 0
+
def self.foo
@@foo
end
+
def self.foo=(value)
@@foo = value
end
end
-```
-### Abgeleitete Klasse
-```
+# Abgeleitete Klasse
class Worker < Human
end
-Human.foo # 0
-Worker.foo # 0
-Human.foo = 2 # 2
-Worker.foo # 2
-```
-### Eine Klasseninstanzvariable wird nicht geteilt
-```
+Human.foo #=> 0
+Worker.foo #=> 0
+
+Human.foo = 2
+Worker.foo #=> 2
+
+# Ableitungen einer Klasse haben keinen Zugriff auf eine Eine Klassen-Instanzvariable.
class Human
@bar = 0
+
def self.bar
@bar
end
+
def self.bar=(value)
@bar = value
end
end
-```
-```
+
class Doctor < Human
end
-```
-```
-Human.bar # 0
-Doctor.bar # nil
-```
-```
+
+Human.bar #=> 0
+Doctor.bar #=> nil
+
module ModuleExample
def foo
'foo'
end
end
-```
-### Module einbinden, heisst ihre Methoden an die Instanzen der Klasse zu binden
-### Module erweitern, heisst ihre Mothden an die Klasse selbst zu binden
-```
+
+# Ein Einbinden (include) eines Moduls bindet seine Methoden an die Instanzen
+# der Klasse.
+# Ein Erweitern (extend) eines Moduls bindet seine Methoden an die Klasse
+# selbst.
class Person
include ModuleExample
end
-```
-```
+
class Book
extend ModuleExample
end
-```
-```
-Person.foo # => NoMethodError: undefined method `foo' for Person:Class
-Person.new.foo # => 'foo'
-Book.foo # => 'foo'
-Book.new.foo # => NoMethodError: undefined method `foo'
-```
-### Callbacks werden ausgeführt, wenn ein Modul eingebunden oder erweitert wird
-```
- module ConcernExample
- def self.included(base)
- base.extend(ClassMethods)
- base.send(:include, InstanceMethods)
- end
- module ClassMethods
- def bar
- 'bar'
- end
- end
- module InstanceMethods
- def qux
- 'qux'
- end
+
+Person.foo #=> NoMethodError: undefined method `foo' for Person:Class
+Person.new.foo #=> "foo"
+Book.foo #=> "foo"
+Book.new.foo #=> NoMethodError: undefined method `foo'
+
+
+# Callbacks werden ausgeführt, wenn ein Modul eingebunden oder erweitert wird.
+module ConcernExample
+ def self.included(base)
+ base.extend(ClassMethods)
+ base.send(:include, InstanceMethods)
+ end
+
+ module ClassMethods
+ def bar
+ 'bar'
end
end
- class Something
- include ConcernExample
+
+ module InstanceMethods
+ def qux
+ 'qux'
+ end
end
-```
-```
-Something.bar # => 'bar'
-Something.qux # => NoMethodError: undefined method `qux'
-Something.new.bar # => NoMethodError: undefined method `bar'
-Something.new.qux # => 'qux'
+end
+
+class Something
+ include ConcernExample
+end
+
+Something.bar #=> "bar"
+Something.qux #=> NoMethodError: undefined method `qux'
+Something.new.bar #=> NoMethodError: undefined method `bar'
+Something.new.qux #=> "qux"
```
-## Weiterführende Hinweise
+## Weitere Links
-//EN
+_(z.T. auf Englisch)_
-- [Learn Ruby by Example with Challenges](http://www.learneroo.com/modules/61/nodes/338) - A variant of this reference with in-browser challenges.
-- [Official Documentation](http://www.ruby-doc.org/core-2.1.1/)
+- [Offizielle Ruby Website](https://www.ruby-lang.org/de/)
+- [Learn Ruby by Example with Challenges](http://www.learneroo.com/modules/61/nodes/338) - Eine Variante dieses Dokuments mit in-Browser Challenges.
+- [RubyMonk](https://rubymonk.com/) - Lerne Ruby mit einer Reihe interaktiver Tutorials.
+- [Offizielle Dokumentation](http://ruby-doc.org/core)
- [Ruby from other languages](https://www.ruby-lang.org/en/documentation/ruby-from-other-languages/)
-- [Programming Ruby](http://www.amazon.com/Programming-Ruby-1-9-2-0-Programmers/dp/1937785491/) - An older [free edition](http://ruby-doc.com/docs/ProgrammingRuby/) is available online.
-- [Ruby Style Guide](https://github.com/bbatsov/ruby-style-guide) - A community-driven Ruby coding style guide.
+- [Programming Ruby](http://www.amazon.com/Programming-Ruby-1-9-2-0-Programmers/dp/1937785491/) - Eine ältere [freie Ausgabe](http://ruby-doc.com/docs/ProgrammingRuby/) ist online verfügbar.
+- [Ruby Style Guide](https://github.com/bbatsov/ruby-style-guide) - Ein von der Community erstellter Ruby coding style guide.
+- [Try Ruby](http://tryruby.org) - Lerne die Grundlagen der Ruby Programmiersprache, interaktiv im Browser.
diff --git a/de-de/scala-de.html.markdown b/de-de/scala-de.html.markdown
index 456403a2..a8344e6a 100644
--- a/de-de/scala-de.html.markdown
+++ b/de-de/scala-de.html.markdown
@@ -8,89 +8,90 @@ contributors:
- ["Dennis Keller", "github.com/denniskeller"]
translators:
- ["Christian Albrecht", "https://github.com/coastalchief"]
+ - ["Jonas Grote", "https://github.com/exic"]
filename: learnscala-de.scala
lang: de-de
---
-Scala ist eine funktionale und objektorientierte Programmiersprache
-für die Java Virtual Machine (JVM), um allgemeine Programmieraufgaben
-zu erledigen. Scala hat einen akademischen Hintergrund und wurde an
+Scala ist eine funktionale und objektorientierte Programmiersprache
+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.
-```scala
+```scala
/*
-Scala Umgebung einrichten:
+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
+3. das Unterverzeichnis `bin` 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.
+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-Grundlagen.
*/
/////////////////////////////////////////////////
-// 1. Basics
+// 1. Grundlagen
/////////////////////////////////////////////////
-// Einzeilige Kommentare beginnen mit zwei Slashes
+// Einzeilige Kommentare beginnen mit zwei Schrägstrichen.
/*
- Mehrzeilige Kommentare, starten
- mit einem Slash-Stern und enden mit einem Stern-Slash
+ Mehrzeilige Kommentare starten mit Schrägstrich und Stern
+ und enden mit Stern und Schrägstrich.
*/
-// Einen Wert, und eine zusätzliche neue Zeile ausgeben
+// Einen Wert und eine zusätzliche neue Zeile ausgeben:
-println("Hello world!")
+println("Hallo Welt!")
println(10)
-// Einen Wert, ohne eine zusätzliche neue Zeile ausgeben
+// Einen Wert ohne eine zusätzliche neue Zeile ausgeben:
-print("Hello world")
+print("Hallo Welt")
/*
- 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
+x = 20 // Error: reassignment to val (Fehler: neue Zuweisung zu einem unveränderlichen Wert)
var y = 10
y = 20 // y ist jetzt 20
/*
-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. 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:
+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. Das heißt, dass der
+Scala Compiler in den meisten Fällen erraten kann, von welchem 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
+// Bei automatischer Umwandlung von Int auf Double wird aus 10 eine 10.0:
val b: Double = 10
-// Boolean Werte
+// Boolean-Werte:
true
false
-// Boolean Operationen
+// Boolean-Operationen:
!true // false
!false // true
@@ -98,7 +99,7 @@ true == false // false
10 > 5 // true
-// Mathematische Operationen sind wie gewohnt
+// Mathematische Operationen sind wie gewohnt:
1 + 1 // 2
2 - 1 // 1
@@ -108,88 +109,87 @@ true == false // false
6.0 / 4 // 1.5
-// Die Auswertung eines Ausdrucks in der REPL gibt den Typ
-// und das Ergebnis zurück.
+// 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...
+Das bedeutet, dass das Resultat der Auswertung von 1 + 7 ein Objekt
+von Typ Int ist und einen Wert 8 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
+"Scala strings werden in doppelten Anführungszeichen eingeschlossen"
+'a' // Ein Scala Char
+// 'Einzeln ge-quotete strings gibt es nicht!' <= Das erzeugt einen Fehler!
-"hello world".length
-"hello world".substring(2, 6)
-"hello world".replace("C", "3")
+// Für Strings gibt es die üblichen Java-Methoden:
+"Hallo Welt".length
+"Hallo Welt".substring(2, 6)
+"Hallo Welt".replace("C", "3")
-// Zusätzlich gibt es noch extra Scala Methoden
-// siehe: scala.collection.immutable.StringOps
-"hello world".take(5)
-"hello world".drop(5)
+// Zusätzlich gibt es noch extra Scala-Methoden
+// siehe: scala.collection.immutable.StringOps
+"Hallo Welt".take(5)
+"Hallo Welt".drop(5)
-// String interpolation: prefix "s"
+
+// String-Interpolation: prefix "s":
val n = 45
-s"We have $n apples" // => "We have 45 apples"
+s"Wir haben $n Äpfel" // => "Wir haben 45 Äpfel"
-// 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"
+s"Meine zweite Tochter ist ${a(0) - a(2)} Jahre alt." // => "Meine zweite Tochter ist 5 Jahre alt."
+s"Wir haben das Doppelte von ${n / 2.0} an Äpfeln." // => "Wir haben das Doppelte von 22.5 an Äpfeln."
+s"2 im Quadrat: ${math.pow(2, 2)}" // => "2 im Quadrat: 4"
-// Formatierung der interpolierten Strings mit dem prefix "f"
+// 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"
+f"5 im Quadrat: ${math.pow(5, 2)}%1.0f" // "5 im Quadrat: 25"
+f"Quadratwurzel von 122: ${math.sqrt(122)}%1.4f" // "Quadratwurzel von 122: 11.0454"
-// Raw Strings, ignorieren Sonderzeichen.
+// 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.
+// Manche Zeichen müssen "escaped" werden, z.B.
+// ein doppeltes Anführungszeichen im Innern eines Strings:
-"They stood outside the \"Rose and Crown\"" // => "They stood outside the "Rose and Crown""
+"Sie standen vor der \"Rose and Crown\"" // => "Sie standen vor der "Rose and Crown""
-// Dreifache Anführungszeichen erlauben es, dass ein String über mehrere Zeilen geht
-// und Anführungszeichen enthalten kann.
+// 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>
+val html = """<form id="dieform">
+ <p>Drück belo', Joe</p>
<input type="submit">
</form>"""
-
+
/////////////////////////////////////////////////
// 2. Funktionen
/////////////////////////////////////////////////
-// Funktionen werden so definiert
-//
-// def functionName(args...): ReturnType = { body... }
-//
-// Beachte: Es gibt kein return Schlüsselwort. In Scala ist der letzte Ausdruck
-// in einer Funktion der Rückgabewert.
+// Funktionen werden so definiert:
+//
+// def functionName(args...): ReturnType = { body... }
+//
+// Beachte: Es wird hier kein Schlüsselwort "return" verwendet.
+// In Scala ist der letzte Ausdruck in einer Funktion der Rückgabewert.
def sumOfSquares(x: Int, y: Int): Int = {
val x2 = x * x
@@ -198,118 +198,118 @@ def sumOfSquares(x: Int, y: Int): Int = {
}
-// Die geschweiften Klammern können weggelassen werden, wenn
-// die Funktion nur aus einem einzigen Ausdruck besteht:
+// 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:
+// 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:
+// In den meisten Fällen (mit Ausnahme von rekursiven Funktionen) können
+// Rückgabetypen auch weggelassen werden, da dieselbe Typ-Inferenz, 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:
+// 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:
+// 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.
+// 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:
+// 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.
+// 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
+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:
+// Es gibt ein Schlüsselwort "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)
- return z // Zeile macht z zum return Wert von foo
- else
- z + 2 // Zeile ist der return Wert von anonFunc
- }
- anonFunc(x) // Zeile ist der return Wert von foo
-}
+def foo(x: Int): Int = {
+ val anonFunc: Int => Int = { z =>
+ if (z > 5)
+ return z // Zeile macht z zum return Wert von foo
+ else
+ z + 2 // Zeile ist der return Wert von anonFunc
+ }
+ anonFunc(x) // Zeile ist der return Wert von foo
+}
/////////////////////////////////////////////////
-// 3. Flow Control
+// 3. Flusskontrolle
/////////////////////////////////////////////////
-// Wertebereiche und Schleifen
+// 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 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
+// 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.
-// While in Scala läuft schneller ab als in Java und die o.g.
-// Kombinatoren und Zusammenlegungen sind einfacher zu verstehen
-// und zu parellelisieren.
+// Beachte: while ist eine Schleife im klassischen Sinne -
+// Sie läuft sequentiell ab und verändert die loop-Variable.
+// "while" in Scala läuft schneller ab als in Java und die o.g.
+// Kombinatoren und Zusammenlegungen sind einfacher zu verstehen
+// und zu parallelisieren.
-// Ein do while Schleife
+// Ein do while Schleife
do {
- println("x ist immer noch weniger wie 10")
+ println("x ist immer noch weniger als 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.
+// Endrekursionen sind idiomatisch um sich wiederholende
+// Aufgaben in Scala zu lösen. Rekursive Funtionen benötigen explizit einen
+// Rückgabe-Typ, der Compiler kann ihn nicht erraten.
+// Der Rückgabe-Typ in diesem Beispiel ist Unit:
def showNumbersInRange(a: Int, b: Int): Unit = {
print(a)
@@ -331,7 +331,7 @@ val text = if (x == 10) "yeah" else "nope"
/////////////////////////////////////////////////
-// 4. Daten Strukturen (Array, Map, Set, Tuples)
+// 4. Datenstrukturen (Array, Map, Set, Tupel)
/////////////////////////////////////////////////
// Array
@@ -344,11 +344,11 @@ a(21) // Exception
// Map - Speichert Key-Value-Paare
-val m = Map("fork" -> "tenedor", "spoon" -> "cuchara", "knife" -> "cuchillo")
+val m = Map("fork" -> "Gabel", "spoon" -> "Löffel", "knife" -> "Messer")
m("fork")
m("spoon")
m("bottle") // Exception
-val safeM = m.withDefaultValue("no lo se")
+val safeM = m.withDefaultValue("unbekannt")
safeM("bottle")
// Set - Speichert Unikate, unsortiert (sortiert -> SortedSet)
@@ -359,8 +359,8 @@ 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
-// Ein Tuple ist keine Collection.
+// Tupel - Speichert beliebige Daten und "verbindet" sie miteinander
+// Ein Tupel ist keine Collection.
(1, 2)
(4, 3, 2)
@@ -368,15 +368,15 @@ s: scala.collection.immutable.Set[Int] = Set(1, 3, 7)
(a, 2, "three")
-// Hier ist der Rückgabewert der Funktion ein Tuple
-// Die Funktion gibt das Ergebnis, so wie den Rest zurück.
+// Hier ist der Rückgabewert der Funktion ein Tupel
+// Die Funktion gibt das Ergebnis sowie 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)
+// Um die Elemente eines Tupels anzusprechen, benutzt man diese
+// Notation: _._n wobei n der index des Elements ist (Index startet bei 1)
val d = divideInts(10, 3)
d._1
@@ -388,32 +388,32 @@ d._2
/////////////////////////////////////////////////
/*
- 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:
+ Bislang waren alle gezeigten Sprachelemente einfache Ausdrücke, welche zwar
+ zum Ausprobieren und Lernen in der REPL gut geeignet sind, jedoch in
+ einer Scala-Datei 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
-// Zum Erstellen von Objekten benötigt man eine Klasse, wie in vielen
-// anderen Sprachen auch.
+// Zum Erstellen von Objekten benötigt man eine Klasse, wie in vielen
+// anderen Sprachen auch.
-// erzeugt Klasse mit default Konstruktor
+// erzeugt Klasse mit default Konstruktor:
class Hund
scala> val t = new Hund
t: Hund = Hund@7103745
-// Der Konstruktor wird direkt hinter dem Klassennamen deklariert.
+// Der Konstruktor wird direkt hinter dem Klassennamen deklariert.
class Hund(sorte: String)
scala> val t = new Hund("Dackel")
@@ -421,8 +421,8 @@ 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
+// 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")
@@ -431,14 +431,14 @@ scala> t.sorte
res18: String = Dackel
-// Methoden werden mit def geschrieben
+// Methoden werden mit def geschrieben
-def bark = "Woof, woof!"
+def bark = "Wuff, wuff!"
-// Felder und Methoden können public, protected und private sein
-// default ist public
-// private ist nur innerhalb des deklarierten Bereichs sichtbar
+// 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 = ...
@@ -446,8 +446,8 @@ class Hund {
}
-// protected ist nur innerhalb des deklarierten und aller
-// erbenden Bereiche sichtbar
+// protected ist nur innerhalb des deklarierten und aller
+// erbenden Bereiche sichtbar
class Hund {
protected def x = ...
@@ -457,12 +457,12 @@ class Dackel extends Hund {
}
// 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.
+// 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
+// verwenden, ohne ein Objekt instanziieren zu müssen.
+// Ein gültiges companion Objekt einer Klasse ist es aber erst dann, wenn
+// es genauso heißt und in derselben Datei wie die Klasse definiert wurde.
object Hund {
def alleSorten = List("Pitbull", "Dackel", "Retriever")
@@ -470,50 +470,51 @@ object Hund {
}
// 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)
+// Fallklassen bzw. Case classes sind Klassen, die normale Klassen um
+// zusätzliche 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.
+// 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"
+// Für neue Instanzen braucht man kein "new":
val dackel = Hund("dackel", "grau", Person("peter"))
val dogge = Hund("dogge", "grau", Person("peter"))
-
-// getter
+
+// getter
dackel.halter // => Person = Person(peter)
-
-// equals
+
+// equals
dogge == dackel // => false
-
-// copy
-// otherGeorge == Person("george", "9876")
+
+// 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.
+// Ä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
@@ -527,22 +528,23 @@ class Bernhardiner extends Hund{
def beissen = false
}
-
-scala> b
-res0: Bernhardiner = Bernhardiner@3e57cd70
-scala> b.sorte
-res1: String = Bernhardiner
-scala> b.bellen
-res2: Boolean = true
-scala> b.beissen
-res3: Boolean = false
+scala> b
+res0: Bernhardiner = Bernhardiner@3e57cd70
+scala> b.sorte
+res1: String = Bernhardiner
+scala> b.bellen
+res2: Boolean = true
+scala> b.beissen
+res3: Boolean = false
-// Traits können auch via Mixins (Schlüsselwort "with") eingebunden werden
+// Ein Trait kann auch als Mixin eingebunden werden. Die Klasse erbt vom
+// ersten Trait mit dem Schlüsselwort "extends", während weitere Traits
+// mit "with" verwendet werden können.
trait Bellen {
- def bellen: String = "Woof"
+ def bellen: String = "Wuff"
}
trait Hund {
def sorte: String
@@ -555,17 +557,17 @@ class Bernhardiner extends Hund with Bellen{
scala> val b = new Bernhardiner
b: Bernhardiner = Bernhardiner@7b69c6ba
scala> b.bellen
-res0: String = Woof
+res0: String = Wuff
/////////////////////////////////////////////////
-// 6. Pattern Matching
+// 6. Mustervergleich (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.
+// 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 {
@@ -575,19 +577,19 @@ x match {
}
-// Pattern Matching kann auf beliebige Typen prüfen
+// Pattern Matching kann auf beliebige Typen prüfen
val any: Any = ...
val gleicht = any match {
case 2 | 3 | 5 => "Zahl"
- case "woof" => "String"
+ case "wuff" => "String"
case true | false => "Boolean"
case 45.35 => "Double"
case _ => "Unbekannt"
}
-// und auf Objektgleichheit
+// und auf Objektgleichheit
def matchPerson(person: Person): String = person match {
case Person("George", nummer) => "George! Die Nummer ist " + number
@@ -596,31 +598,31 @@ def matchPerson(person: Person): String = person match {
}
-// Und viele mehr...
+// Und viele mehr...
val email = "(.*)@(.*)".r // regex
def matchEverything(obj: Any): String = obj match {
// Werte:
- case "Hello world" => "Got the string Hello world"
+ case "Hallo Welt" => "string Hallo Welt gefunden"
// Typen:
- case x: Double => "Got a Double: " + x
- // Conditions:
- case x: Int if x > 10000 => "Got a pretty big number!"
- // Case Classes:
- case Person(name, number) => s"Got contact info for $name!"
+ case x: Double => "Double gefunden: " + x
+ // Bedingungen:
+ case x: Int if x > 10000 => "Ziemlich große Zahl gefunden!"
+ // Case-Klassen:
+ case Person(name, number) => s"Kontaktinformationen für $name gefunden!"
// RegEx:
- case email(name, domain) => s"Got email address $name@$domain"
- // Tuples:
- case (a: Int, b: Double, c: String) => s"Got a tuple: $a, $b, $c"
+ case email(name, domain) => s"E-Mail-Adresse $name@$domain gefunden"
+ // Tupel:
+ case (a: Int, b: Double, c: String) => s"Tupel gefunden: $a, $b, $c"
// Strukturen:
- case List(1, b, c) => s"Got a list with three elements and starts with 1: 1, $b, $c"
- // Patterns kann man ineinander schachteln:
- case List(List((1, 2, "YAY"))) => "Got a list of list of tuple"
+ case List(1, b, c) => s"Liste aus drei Elementen gefunden, startend mit 1: 1, $b, $c"
+ // Pattern kann man ineinander schachteln:
+ case List(List((1, 2, "YAY"))) => "Liste von Tupeln gefunden"
}
-// Jedes Objekt mit einer "unapply" Methode kann per Pattern geprüft werden
-// Ganze Funktionen können Patterns sein
+// 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"
@@ -629,58 +631,58 @@ val patternFunc: Person => String = {
/////////////////////////////////////////////////
-// 37. Higher-order functions
+// 7. "Higher-order"-Funktionen
/////////////////////////////////////////////////
-Scala erlaubt, das Methoden und Funktion wiederum Funtionen und Methoden
-als Aufrufparameter oder Return Wert verwenden. Diese Methoden heissen
-higher-order functions
-Es gibt zahlreiche higher-order functions nicht nur für Listen, auch für
-die meisten anderen Collection Typen, sowie andere Klassen in Scala
-Nennenswerte sind:
-"filter", "map", "reduce", "foldLeft"/"foldRight", "exists", "forall"
+// Scala erlaubt, dass Methoden und Funktionen wiederum Funtionen und Methoden
+// als Aufrufparameter oder Rückgabewert verwenden. Diese Methoden heißen
+// higher-order functions.
+// Es gibt zahlreiche higher-order-Funtionen nicht nur für Listen, auch für
+// die meisten anderen Collection-Typen, sowie andere Klassen in Scala.
+// Nennenswerte sind:
+// "filter", "map", "reduce", "foldLeft"/"foldRight", "exists", "forall"
-## List
+// List
-def isGleichVier(a:Int) = a == 4
+def istGleichVier(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
+// map
+// map nimmt eine Funktion und führt sie auf jedem Element aus und erzeugt
+// eine neue Liste
-val add10: Int => Int = _ + 10
+// Funktion erwartet einen Int und gibt einen Int zurück:
+val add10: Int => Int = _ + 10
-// add10 wird auf jedes Element angewendet
+
+// 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
+// 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.
+// 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.
+// Wenn der anonyme Block und die Funktion beide EIN Argument erwarten,
+// kann sogar der Unterstrich weggelassen werden.
List("Dom", "Bob", "Natalia") foreach println
// filter
-// filter nimmt ein Prädikat (eine Funktion von A -> Boolean) und findet
-// alle Elemente die auf das Prädikat passen
+// 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)
@@ -691,19 +693,19 @@ List(
// reduce
-// reduce nimmt zwei Elemente und kombiniert sie zu einem Element,
-// und zwar solange bis nur noch ein Element da ist.
+// reduce nimmt zwei Elemente und kombiniert sie zu einem Element,
+// und zwar so lange, bis nur noch ein Element da ist.
// foreach
-// foreach gibt es für einige Collections
+// 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
-// Eine for-comprehension definiert eine Beziehung zwischen zwei Datensets.
-// Dies ist keine for-Schleife.
+// 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)
@@ -715,108 +717,108 @@ for { n <- s; nSquared = n * n if nSquared < 10} yield nSquared
// 8. Implicits
/////////////////////////////////////////////////
-// **ACHTUNG:**
+// **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.
+// Es sehr einfach,
+// sie falsch zu benutzen und Anfänger sollten sie mit Vorsicht oder am
+// besten erst dann benutzen, wenn sie verstehen, wie sie funktionieren.
+// Dieses Tutorial enthält Implicits, da sie in Scala an jeder Stelle
+// vorkommen und man auch mit einer Bibliothek, die Implicits benutzt, sonst
+// 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.
+// 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
+// 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
+// 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!"
+ s"Hallo $toWhom, $howMany Segenswünsche für Sie und Ihre Angehörigen!"
+
+// Werden beide Parameter gefüllt, verhält sich die Funktion wie erwartet
-// Werden beide Parameter gefüllt, verhält sich die Funktion wie erwartet
+sendGreetings("John")(1000) // => "Hallo John, 1000 Segenswünsche für Sie und Ihre Angehörigen!"
-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
+// lexikalischen Scope und im companion object nach einem implicit-Wert,
+// der vom Typ passt, oder nach einer implicit-Methode, mit der er in den
+// geforderten Typ konvertieren kann.
-// Wird der implicit Parameter jedoch weggelassen, wird ein anderer
-// implicit Wert vom gleichen Typ genommen. Der Compiler sucht im
-// lexikalischen Scope und im companion object nach einem implicit Wert,
-// der vom Typ passt, oder nach einer implicit Methode mit der er in den
-// geforderten Typ konvertieren kann.
-
-// Hier also: "myImplicitInt", da ein Int gesucht wird
+// Hier also: "myImplicitInt", da ein Int gesucht wird
-sendGreetings("Jane") // => "Hello Jane, 100 blessings to you and yours!"
+sendGreetings("Jane") // => "Hallo Jane, 100 Segenswünsche für Sie und Ihre Angehörigen!"
-// bzw. "myImplicitFunction"
-// Der String wird erst mit Hilfe der Funktion in Hund konvertiert, und
-// dann wird die Methode aufgerufen
+// bzw. "myImplicitFunction"
+// Der String wird erst mit Hilfe der Funktion in Hund konvertiert,
+// dann wird die Methode aufgerufen:
"Retriever".sorte // => "Golden Retriever"
/////////////////////////////////////////////////
-// 19. Misc
+// 9. Sonstiges
/////////////////////////////////////////////////
// Importe
import scala.collection.immutable.List
-// Importiere alle Unterpackages
+// Importiere alle Unterpackages
import scala.collection.immutable._
-// Importiere verschiedene Klassen mit einem Statement
+// Importiere verschiedene Klassen mit einem Statement
import scala.collection.immutable.{List, Map}
-// Einen Import kann man mit '=>' umbenennen
+// Einen Import kann man mit '=>' umbenennen
import scala.collection.immutable.{List => ImmutableList}
-// Importiere alle Klasses, mit Ausnahem von....
-// Hier ohne: Map and Set:
+// 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 = {
- // Sachen kommen hierhin
+ // Zeugs hier rein.
}
}
// I/O
-// Eine Datei Zeile für Zeile lesen
+// Eine Datei Zeile für Zeile lesen
import scala.io.Source
for(line <- Source.fromFile("myfile.txt").getLines())
println(line)
-// Eine Datei schreiben
+// Eine Datei schreiben
val writer = new PrintWriter("myfile.txt")
writer.write("Schreibe Zeile" + util.Properties.lineSeparator)
@@ -825,13 +827,13 @@ writer.close()
```
-## Weiterführende Hinweise
+## Weiterführende Hinweise
-// DE
+### DE
* [Scala Tutorial](https://scalatutorial.wordpress.com)
* [Scala Tutorial](http://scalatutorial.de)
-// EN
+### EN
* [Scala for the impatient](http://horstmann.com/scala/)
* [Twitter Scala school](http://twitter.github.io/scala_school/)
* [The scala documentation](http://docs.scala-lang.org/)
diff --git a/de-de/shutit-de.html.markdown b/de-de/shutit-de.html.markdown
new file mode 100644
index 00000000..29ed639e
--- /dev/null
+++ b/de-de/shutit-de.html.markdown
@@ -0,0 +1,330 @@
+---
+category: tool
+filename: learnshutit-de.html
+tool: ShutIt
+contributors:
+ - ["Ian Miell", "http://ian.meirionconsulting.tk"]
+translators:
+ - ["Dennis Keller", "https://github.com/denniskeller"]
+lang: de-de
+---
+
+## ShutIt
+
+ShuIt ist eine Shellautomationsframework, welches für eine einfache
+Handhabung entwickelt wurde.
+
+Er ist ein Wrapper, der auf einem Python expect Klon (pexpect) basiert.
+
+Es ist damit ein 'expect ohne Schmerzen'.
+
+Es ist verfügbar als pip install.
+
+## Hello World
+
+Starten wir mit dem einfachsten Beispiel. Erstelle eine Datei names example.py
+
+```python
+
+import shutit
+session = shutit.create_session('bash')
+session.send('echo Hello World', echo=True)
+```
+
+Führe es hiermit aus:
+
+```bash
+python example.py
+```
+
+gibt aus:
+
+```bash
+$ python example.py
+echo "Hello World"
+echo "Hello World"
+Hello World
+Ians-MacBook-Air.local:ORIGIN_ENV:RhuebR2T#
+```
+
+Das erste Argument zu 'send' ist der Befehl, den du ausführen möchtest.
+Das 'echo' Argument gibt die Terminalinteraktion aus. ShuIt ist standardmäßig leise.
+
+'Send' kümmert sich um die nervige Arbeiten mit den Prompts und macht
+alles was du von 'expect' erwarten würdest.
+
+
+## Logge dich auf einen Server ein
+
+Sagen wir du möchtest dich auf einen Server einloggen und einen Befehl ausführen.
+Ändere dafür example.py folgendermaßen:
+
+```python
+import shutit
+session = shutit.create_session('bash')
+session.login('ssh you@example.com', user='du', password='meinpassword')
+session.send('hostname', echo=True)
+session.logout()
+```
+
+Dies erlaubt dir dich auf deinen Server einzuloggen
+(ersetze die Details mit deinen Eigenen) und das Programm gibt dir deinen Hostnamen aus.
+
+```
+$ python example.py
+hostname
+hostname
+example.com
+example.com:cgoIsdVv:heDa77HB#
+```
+
+
+Es ist klar das das nicht sicher ist. Stattdessen kann man Folgendes machen:
+
+```python
+import shutit
+session = shutit.create_session('bash')
+password = session.get_input('', ispass=True)
+session.login('ssh you@example.com', user='du', password=password)
+session.send('hostname', echo=True)
+session.logout()
+```
+
+Dies zwingt dich dein Passwort einzugeben:
+
+```
+$ python example.py
+Input Secret:
+hostname
+hostname
+example.com
+example.com:cgoIsdVv:heDa77HB#
+```
+
+
+Die 'login' Methode übernimmt wieder das veränderte Prompt für den Login.
+Du übergibst ShutIt den User und das Passwort, falls es benötigt wird,
+mit den du dich einloggen möchtest. ShutIt übernimmt den Rest.
+
+'logout' behandelt das Ende von 'login' und übernimmt alle Veränderungen des
+Prompts für dich.
+
+## Einloggen auf mehrere Server
+
+Sagen wir, dass du eine Serverfarm mit zwei Servern hast und du dich in
+beide Server einloggen möchtest. Dafür musst du nur zwei Session und
+Logins erstellen und kannst dann Befehle schicken:
+
+```python
+import shutit
+session1 = shutit.create_session('bash')
+session2 = shutit.create_session('bash')
+password1 = session1.get_input('Password für server1', ispass=True)
+password2 = session2.get_input('Password für server2', ispass=True)
+session1.login('ssh you@one.example.com', user='du', password=password1)
+session2.login('ssh you@two.example.com', user='du', password=password2)
+session1.send('hostname', echo=True)
+session2.send('hostname', echo=True)
+session1.logout()
+session2.logout()
+```
+
+Gibt aus:
+
+```bash
+$ python example.py
+Password for server1
+Input Secret:
+
+Password for server2
+Input Secret:
+hostname
+hostname
+one.example.com
+one.example.com:Fnh2pyFj:qkrsmUNs# hostname
+hostname
+two.example.com
+two.example.com:Gl2lldEo:D3FavQjA#
+```
+
+## Beispiel: Überwachen mehrerer Server
+
+Wir können das obige Programm in ein einfaches Überwachungstool bringen indem
+wir Logik hinzufügen um die Ausgabe von einem Befehl zu betrachten.
+
+```python
+import shutit
+capacity_command="""df / | awk '{print $5}' | tail -1 | sed s/[^0-9]//"""
+session1 = shutit.create_session('bash')
+session2 = shutit.create_session('bash')
+password1 = session.get_input('Passwort für Server1', ispass=True)
+password2 = session.get_input('Passwort für Server2', ispass=True)
+session1.login('ssh you@one.example.com', user='du', password=password1)
+session2.login('ssh you@two.example.com', user='du', password=password2)
+capacity = session1.send_and_get_output(capacity_command)
+if int(capacity) < 10:
+ print(kein Platz mehr auf Server1!')
+capacity = session2.send_and_get_output(capacity_command)
+if int(capacity) < 10:
+ print(kein Platz mehr auf Server2!')
+session1.logout()
+session2.logout()
+```
+
+Hier kannst du die 'send\_and\_get\_output' Methode verwenden um die Ausgabe von dem
+Kapazitätsbefehl (df) zu erhalten.
+
+Es gibt elegantere Wege als oben (z.B. kannst du ein Dictionary verwenden um über
+die Server zu iterieren), aber es hängt and dir wie clever das Python sein muss.
+
+
+## kompliziertere IO - Expecting
+
+Sagen wir du hast eine Interaktion mit einer interaktiven Kommandozeilenprogramm,
+die du automatisieren möchtest. Hier werden wir Telnet als triviales Beispiel verwenden:
+
+```python
+import shutit
+session = shutit.create_session('bash')
+session.send('telnet', expect='elnet>', echo=True)
+session.send('open google.com 80', expect='scape character', echo=True)
+session.send('GET /', echo=True, check_exit=False)
+session.logout()
+```
+
+Beachte das 'expect' Argument. Du brauchst nur ein Subset von Telnets
+Eingabeaufforderung um es abzugleichen und fortzufahren.
+
+Beachte auch das neue Argument 'check\_exit'. Wir werden nachher nochmal
+darauf zurückkommen. Die Ausgabe von oben ist:
+
+```bash
+$ python example.py
+telnet
+telnet> open google.com 80
+Trying 216.58.214.14...
+Connected to google.com.
+Escape character is '^]'.
+GET /
+HTTP/1.0 302 Found
+Cache-Control: private
+Content-Type: text/html; charset=UTF-8
+Referrer-Policy: no-referrer
+Location: http://www.google.co.uk/?gfe_rd=cr&ei=huczWcj3GfTW8gfq0paQDA
+Content-Length: 261
+Date: Sun, 04 Jun 2017 10:57:10 GMT
+
+<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
+<TITLE>302 Moved</TITLE></HEAD><BODY>
+<H1>302 Moved</H1>
+The document has moved
+<A HREF="http://www.google.co.uk/?gfe_rd=cr&amp;ei=huczWcj3GfTW8gfq0paQDA">
+here
+</A>.
+</BODY></HTML>
+Connection closed by foreign host.
+```
+
+Nun zurück zu 'check\_exit=False'. Da das Telnet Programm einen Fehler mit
+Fehlercode (1) zurückgibt und wir nicht möchten das das Skript fehlschlägt
+kannst du 'check\_exit=False' setzen und damit ShuIt wissen lassen, dass
+der Ausgabecode dich nicht interessiert.
+
+Wenn du das Argument nicht mitgegeben hättest, dann hätte dir ShutIt
+ein interaktives Terminal zurückgegeben, falls es ein Terminal zum
+kommunizieren gibt. Dies nennt sich ein 'Pause point'.
+
+
+## Pause Points
+
+Du kannst jederzeit 'pause point' auslösen, wenn du Folgendes in deinem Skript aufrufst:
+
+```python
+[...]
+session.pause_point('Das ist ein pause point')
+[...]
+```
+
+Danach kannst du das Skript fortführen, wenn du CTRL und ']' zur selben Zeit drückst.
+Dies ist gut für Debugging: Füge ein Pause Point hinzu und schaue dich um.
+Danach kannst du das Programm weiter ausführen. Probiere folgendes aus:
+
+```python
+import shutit
+session = shutit.create_session('bash')
+session.pause_point('Schaue dich um!')
+session.send('echo "Hat dir der Pause point gefallen?"', echo=True)
+```
+
+Dies würde folgendes ausgeben:
+
+```bash
+$ python example.py
+Schaue dich um!
+
+Ians-Air.home:ORIGIN_ENV:I00LA1Mq# bash
+imiell@Ians-Air:/space/git/shutit ⑂ master + 
+CTRL-] caught, continuing with run...
+2017-06-05 15:12:33,577 INFO: Sending: exit
+2017-06-05 15:12:33,633 INFO: Output (squashed): exitexitIans-Air.home:ORIGIN_ENV:I00LA1Mq# [...]
+echo "Hat dir der Pause point gefallen?"
+echo "Hat dir der Pause point gefallen?"
+Hat dir der Pause point gefallen?
+Ians-Air.home:ORIGIN_ENV:I00LA1Mq#
+```
+
+
+## noch kompliziertere IO - Hintergrund
+
+Kehren wir zu unseren Beispiel mit dem Überwachen von mehreren Servern zurück.
+Stellen wir uns vor, dass wir eine langlaufende Aufgabe auf jedem Server durchführen möchten.
+Standardmäßig arbeitet ShutIt seriell, was sehr lange dauern würde.
+Wir können jedoch die Aufgaben im Hintergrund laufen lassen um sie zu beschleunigen.
+
+Hier ist ein Beispiel, welches du ausprobieren kannst.
+Es verwendet den trivialen Befehl: 'sleep'.
+
+
+```python
+import shutit
+import time
+long_command="""sleep 60"""
+session1 = shutit.create_session('bash')
+session2 = shutit.create_session('bash')
+password1 = session1.get_input('Password for server1', ispass=True)
+password2 = session2.get_input('Password for server2', ispass=True)
+session1.login('ssh you@one.example.com', user='du', password=password1)
+session2.login('ssh you@two.example.com', user='du', password=password2)
+start = time.time()
+session1.send(long_command, background=True)
+session2.send(long_command, background=True)
+print('Es hat: ' + str(time.time() - start) + ' Sekunden zum Starten gebraucht')
+session1.wait()
+session2.wait()
+print('Es hat:' + str(time.time() - start) + ' Sekunden zum Vollenden gebraucht')
+```
+
+Mein Computer meint, dass er 0.5 Sekunden gebraucht hat um die Befehle zu starten
+und dann nur etwas über eine Minute gebraucht um sie zu beenden
+(mit Verwendung der 'wait' Methode).
+
+
+Das alles ist trivial, aber stelle dir vor das du hunderte an Servern so managen
+kannst und man kann nun das Potential sehen, die in ein paar Zeilen Code und ein Python
+import liegen können.
+
+
+## Lerne mehr
+
+Es gibt noch viel mehr, was mit ShutIt erreicht werden kann.
+
+Um mehr zu erfahren, siehe:
+
+[ShutIt](https://ianmiell.github.io/shutit/)
+[GitHub](https://github.com/ianmiell/shutit/blob/master/README.md)
+
+Es handelt sich um ein breiteres Automatiesierungsframework, und das oben
+genannte ist der sogennante 'standalone Modus'.
+
+Feedback, feature requests, 'Wie mache ich es' sind herzlich willkommen! Erreiche mit unter
+[@ianmiell](https://twitter.com/ianmiell)
diff --git a/de-de/swift-de.html.markdown b/de-de/swift-de.html.markdown
index b58a72d3..08f72a35 100644
--- a/de-de/swift-de.html.markdown
+++ b/de-de/swift-de.html.markdown
@@ -440,13 +440,13 @@ if let circle = myEmptyCircle {
// Wie Klassen auch können sie Methoden haben
enum Suit {
- case Spades, Hearts, Diamonds, Clubs
+ case spades, hearts, diamonds, clubs
func getIcon() -> String {
switch self {
- case .Spades: return "♤"
- case .Hearts: return "♡"
- case .Diamonds: return "♢"
- case .Clubs: return "♧"
+ case .spades: return "♤"
+ case .hearts: return "♡"
+ case .diamonds: return "♢"
+ case .clubs: return "♧"
}
}
}
@@ -455,35 +455,35 @@ enum Suit {
// Enum-Werte können vereinfacht geschrieben werden, es muss nicht der Enum-Typ
// genannt werden, wenn die Variable explizit deklariert wurde
-var suitValue: Suit = .Hearts
+var suitValue: Suit = .hearts
// Nicht-Integer-Enums brauchen direkt zugewiesene "Rohwerte"
enum BookName: String {
- case John = "John"
- case Luke = "Luke"
+ case john = "John"
+ case luke = "Luke"
}
-print("Name: \(BookName.John.rawValue)")
+print("Name: \(BookName.john.rawValue)")
// Enum mit assoziierten Werten
enum Furniture {
// mit Int assoziiert
- case Desk(height: Int)
+ case desk(height: Int)
// mit String und Int assoziiert
- case Chair(String, Int)
-
+ case chair(String, Int)
+
func description() -> String {
switch self {
- case .Desk(let height):
+ case .desk(let height):
return "Desk with \(height) cm"
- case .Chair(let brand, let height):
+ case .chair(let brand, let height):
return "Chair of \(brand) with \(height) cm"
}
}
}
-var desk: Furniture = .Desk(height: 80)
+var desk: Furniture = .desk(height: 80)
print(desk.description()) // "Desk with 80 cm"
-var chair = Furniture.Chair("Foo", 40)
+var chair = Furniture.chair("Foo", 40)
print(chair.description()) // "Chair of Foo with 40 cm"
diff --git a/de-de/vim-de.html.markdown b/de-de/vim-de.html.markdown
new file mode 100644
index 00000000..8abf9a14
--- /dev/null
+++ b/de-de/vim-de.html.markdown
@@ -0,0 +1,282 @@
+---
+category: tool
+tool: vim
+lang: de-de
+contributors:
+ - ["RadhikaG", "https://github.com/RadhikaG"]
+translators:
+ - ["caminsha", "https://github.com/caminsha"]
+filename: LearnVim-de.txt
+---
+
+
+[Vim](http://www.vim.org)
+(Vi IMproved) ist ein Klon von vi, dem bekannten Editor für Unix. Es ist ein
+Texteditor, welcher mit Fokus auf Geschwindigkeit und Prouktivität entwickelt
+wurde.
+Vim hat viele Keybindings für ein schnelles navigieren und schnelles bearbeiten
+einer Datei.
+
+## Grundlagen, um in Vim zu navigieren
+
+```
+ vim <filename> # Öffne <filename> in Vim
+ :help <topic> # Open up built-in help docs about <topic> if any exists
+ :help <topic> # Öffne die eingebaute Hilfe zum Thema <topic>, wenn
+ # es existiert
+ :q # Schließe vim
+ :w # Speichere diese Datei
+ :wq # Speichere diese Datei und schließe vim
+ ZZ # Speichere diese Datei und schließe vim
+ :q! # Schließe vim ohne die Datei zu speichern
+ # ! *zwingt* die Ausführung von :q,
+ # daher wird die Datei nicht gespeichert.
+ ZQ # Beende vim ohne die Datei zu speichern
+ :x # Speichere die Datei und beende vim
+ # Dies ist eine kürzere Version von :wq
+
+ u # Änderung rückgängig machen
+ CTRL+R # Änderung wiederherstellen
+
+ h # Den Cursor um ein Zeichen nach links bewegen
+ j # Den Cursor eine Zeile nach unten bewegen
+ k # Den Cursor eine Zeile nach oben bewegen
+ l # Den Cursor um ein Zeichen nach rechts bewegen
+
+ Ctrl+B # Gehe eine Bildschirmanzeige zurück
+ Ctrl+F # Gehe eine Bildschirmanzeige vorwärts
+ Ctrl+D # Gehe eine halbe Bildschirmanzeige vorwärts
+ Ctrl+U # Gehe eine halbe Bildschirmanzeige zurück
+
+ # Navigieren innerhalb einer Zeile
+
+ 0 # Navigiere zum Anfang der Zeile
+ $ # Navigiere zum Ende der Zeile
+ ^ # Navigiere zum ersten Zeichen, welches kein Leerzeichen ist
+
+ # Im Text suchen
+
+ /word # Hebt alle Ergebnisse nach dem Cursor hervor
+ ?word # Hebt alle Ergebnisse vor dem Cursor hervor
+ n # Bewegt den Cursor zum nächsten Ergebnis nach der Suche
+ N # Bewegt den Cursor zum vorherigen Ergebnis der Suche
+
+ :%s/foo/bar/g # Ersetze "foo" durch "bar" in allen Zeilen
+ :s/foo/bar/g # Ersetze "foo" durch "bar" in der aktuellen Zeile
+ :%s/\n/\r/g # Ersetze das newline-Zeichen bei allen Zeilen durch
+ # ein carriage return
+
+ # Zu einzelnen Zeichen springen
+
+ f<character> # Springe vorwärts und auf dem Zeichen <character>
+ t<character> # Springe vorwärts und lande vor dem Zeichen <character>
+
+ # Zum Beispiel,
+ f< # Springe vorwärts und lande auf <
+ t< # Springe vorwärts und lande vor <
+
+ # Wortweise navigieren
+
+ w # Springe um ein Wort vorwärts
+ b # Gehe ein Wort zurück
+ e # Springe zum Ende des aktuellen Wortes
+
+ # Weitere Befehle, um zu navigieren
+
+ gg # Gehe an den Start der Datei
+ G # Gehe an das Ende der Datei
+ :NUM # Springe zur Zeile NUM (NUM kann eine beliebige Zahl sein)
+ H # Navigiere zum Start der aktuellen Bildschirmanzeige
+ M # Navigiere in die Mitte der aktuellen Bildschirmanzeige
+ L # Navigiere an das Ende der aktuellen Bildschirmanzeige
+```
+
+## Hilfsdokumente:
+
+Vim hat eine eingebaute Dokumentation, welche mit `:help <topic>` aufgerufen
+werden kann.
+Zum Beispiel öffnet `:help navigation` die Dokumentation über das Navigieren
+
+`:help` kann auch ohne ein Argument verwendet werden. Dies zeigt den Standard-
+Hilfsdialog an, welcher den Start mit vim einfacher macht.
+that aims to make getting started with vim more approachable!
+
+## Modi:
+
+Vim basiert auf dem Konzept von **modes**.
+
+- Command Mode - Vim startet in diesem Modus, hier kann man navigieren und Befehle eingeben
+- Insert Mode - Wird verwendet, um Änderungen in der Datei zu machen.
+- Visual Mode - Wird verwendet, um Text zu markieren und Operationen durchzuführen
+- Ex Mode - Wird verwendet, um im ':'-Prompt Befehle einzugeben
+
+```
+ i # Führt vim in den Insert Mode, vor der Cursorposition
+ a # Führt vim in den Insert Mode, nach der Cursorposition
+ v # Führt vim in den Visual Mode
+ : # Führt vim in den Ex Mode
+ <esc> # Führt zurück in den Command Mode, egal in welchem Mode
+ # man sich gerade befindet.
+
+ # Kopieren und einfügen von Text
+
+ y # Kopiere alles, was im Moment ausgewählt ist
+ yy # Kopiert die aktuelle Zeile
+ d # Löscht alles, was im Moment ausgewählt ist
+ dd # Löscht die aktuelle Zeile
+ p # Fügt den kopierten Text nach dem Cursor ein
+ P # Fügt den kopierten Text vor dem Cursor ein
+ x # Löscht das Zeichen unter dem Cursor
+```
+
+## Die 'Grammatik' von Vim
+
+Vim kann als Satz von Kommandos angesehen werden, welche im Format
+'Verb-Modifier-Noun' sind. Hierbei gilt:
+
+- Verb - die Aktion, du machen willst
+- Modifier - wie die Aktion gemacht wird
+- Noun - das Objekt, auf welchem die Aktion ausgeführt wird.
+
+Einige wichtige Beispiele von 'Verb', 'Modifier' und 'Nouns':
+
+```
+ # 'Verb'
+
+ d # löschen
+ c # ändern
+ y # kopieren
+ v # visuelles auswählen
+
+ # 'Modifiers'
+
+ i # innerhalb
+ a # außerhalb
+ NUM # Nummer (NUM kann irgendeine Zahl sein)
+ f # Sucht nach etwas und landet darauf
+ t # Sucht nach etwas und stoppt davor
+ / # Suche eine Zeichenfolge ab dem Cursor
+ ? # Suche eine Zeichenfolge vor dem Cursor
+
+ # 'Nouns'
+
+ w # Wort
+ s # Satz
+ p # Abschnitt
+ b # Block
+
+ # Beispielsätze resp. Kommandos
+
+ d2w # lösche zwei Wörter
+ cis # Ändere innerhalb des Satzes.
+ yip # Kopiere innerhalb des Abschnitts (kopiere den Abschnitt,
+ # in welchem du bist)
+ ct< # Ändere bis zur spitzen Klammer
+ # Ändere den Text von deiner aktuellen Cursorposition bis
+ # zur nächsten spitzen Klammer
+ d$ # Lösche bis zum Ende der Zeile
+```
+
+## Einige Shortcuts und Tricks
+
+```
+ > # Rücke die Auswahl um einen Block ein
+ < # Lösche eine Einrückung der Auswahl
+ :earlier 15m # Stellt das Dokument so wieder her, wie es vor 15
+ # Minuten war
+ :later 15m # den oberen Befehl rückgängig machen
+ ddp # Vertauschen zweier aufeinanderfolgenden Zeilen
+ # Zuerst dd, dann p
+ . # Wiederhole die vorherige Aktion
+ :w !sudo tee % # Speichere die Datei als Root
+ :set syntax=c # Stelle das Syntax-Highlighting für 'C' ein
+ :sort # Alle Zeilen sortieren
+ :sort! # Alle Zeilen rückwärts sortieren
+ :sort u # Alle Zeilen sortieren und Duplikate entfernen
+ ~ # Umschalten der Groß-/Kleinschreibung des ausgewählten Textes
+ u # Ausgewählten Text zu Kleinschreibung ändern
+ U # Ausgewählten Text zu Großschreibung ändern
+
+ # Text-Folding (Textfaltung)
+ zf # Erstelle eine Faltung des ausgewählten Textes
+ zo # Öffne die aktuelle Faltung
+ zc # Schließe die aktuelle Faltung
+ zR # Öffne alle Faltungen
+ zM # Schließe alle Faltungen
+```
+
+## Makros
+
+Makros sind grundsätzlich einfach aufgezeichnete Aktionen
+Wenn du mit dem Aufnehmen eines Makros beginnst, werden **alle** Aktionen und
+Kommandos, welche du braucht, aufgenommen bis die Aufnahme gestoppt wird.
+Wenn du ein Makro ausführst, werden exakt die gleichen Schritte gemacht.
+
+```
+ qa # Starte das Aufnehmen des Makros 'a'
+ q # Beende das Aufnehmen
+ @a # Führe das Makro 'a' aus
+```
+
+### Konfigurieren mit ~/.vimrc
+
+Die Datei .vimrc kann verwendet werden, um Vim beim Starten zu konfigurieren
+
+Hier ist eine Beispiel ~/.vimrc Datei:
+
+```
+" Beispiel ~/.vimrc
+
+" Erforderlich für vim, dass es iMproved ist.
+set nocompatible
+
+" Bestimme den Dateityp anhand des Namens, um ein intelligentes Einrücken etc.
+" zu ermöglichen
+filetype indent plugin on
+
+" Aktiviere das Syntax-Highlighting
+syntax on
+
+" Bessere Kommandozeilen-Vervollständigung
+set wildmenu
+
+" Verwende die Suche ohne die Berücksichtigung der Groß-/Kleinschreibung, außer
+" wenn mit Großbuchstaben gesucht wird.
+set ignorecase
+set smartcase
+
+" Wenn eine neue Zeile erstellt wird und kein Dateispezifisches Einrücken
+" aktiviert ist, behält die neue Zeile die gleiche Einrückung wie die aktuelle
+" Zeile
+set autoindent
+
+" Zeige links die Zeilennummern an
+set number
+
+" Einrückungsoptionen, ändere diese nach deinen Vorlieben
+
+" Anzahl sichtbarer Leerzeichen bei einem TAB
+set tabstop=4
+
+" Anzahl der Leerzeichen während des Bearbeitens bei einem TAB
+set softtabstop=4
+
+" Anzahl der Einrückungstiefe bei den Operationen (>> und <<)
+set shiftwidth=4
+
+" Konvertiere TABs zu Leerzeichen
+set expandtab
+
+" Enable intelligent tabbing and spacing for indentation and alignment
+" Aktiviere intelligente Tabs und Leerzeichen bei der Einrückung und Ausrichtung
+set smarttab
+```
+
+### Verweise
+
+- [Vim | Homepage](http://www.vim.org/index.php)
+- In der Shell eingeben: `vimtutor`
+- [Ein vim Tutorial und Primer, englisch](https://danielmiessler.com/study/vim/)
+- [Deutsches Arch Linux Wiki](https://wiki.archlinux.de/title/Vim)
+- [Arch Linux Wiki, englisch (dafür ausführlicher)](https://wiki.archlinux.org/index.php/Vim)
+- [What are the dark corners of Vim your mom never told you about? (Stack Overflow thread)](http://stackoverflow.com/questions/726894/what-are-the-dark-corners-of-vim-your-mom-never-told-you-about)
diff --git a/de-de/yaml-de.html.markdown b/de-de/yaml-de.html.markdown
index a46c30f6..0332c912 100644
--- a/de-de/yaml-de.html.markdown
+++ b/de-de/yaml-de.html.markdown
@@ -1,7 +1,7 @@
---
language: yaml
contributors:
- - ["Adam Brenecki", "https://github.com/adambrenecki"]
+ - ["Leigh Brenecki", "https://github.com/adambrenecki"]
translators:
- ["Ruben M.", "https://github.com/switchhax"]
filename: learnyaml-de.yaml
@@ -10,7 +10,7 @@ lang: de-de
YAML ist eine Sprache zur Datenserialisierung, die sofort von Menschenhand geschrieben und gelesen werden kann.
-YAML ist eine Erweiterung von JSON, mit der Erweiterung von syntaktisch wichtigen Zeilenumbrüche und Einrückung sowie in Python. Anders als in Python erlaubt YAML keine Tabulator-Zeichen.
+YAML ist ein Erweiterung von JSON mit der Erweiterung um syntaktisch wichtige Zeilenumbrüche und Einrückungen, ähnlich wie auch in Python geschrieben werden können. Anders als in Python allerdings erlaubt YAML keine Tabulator-Zeichen.
```yaml
# Kommentare in YAML schauen so aus.
@@ -111,7 +111,7 @@ python_komplexe_Zahlen: !!python/komplex 1+2j
# EXTRA YAML TYPEN #
####################
-# Strings and Zahlen sind nicht die einzigen Skalare, welche YAML versteht.
+# Strings und Zahlen sind nicht die einzigen Skalare, welche YAML versteht.
# ISO-formatierte Datumsangaben and Zeiangaben können ebenso geparsed werden.
DatumZeit: 2001-12-15T02:59:43.1Z
DatumZeit_mit_Leerzeichen: 2001-12-14 21:59:43.10 -5