From 593bcb9ae4b0ab603319130e58a5d0521cd4b498 Mon Sep 17 00:00:00 2001 From: Christian Albrecht Date: Fri, 16 Oct 2015 14:13:49 +0200 Subject: scala translation de --- de-de/scala-de.html.markdown | 810 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 810 insertions(+) create mode 100644 de-de/scala-de.html.markdown diff --git a/de-de/scala-de.html.markdown b/de-de/scala-de.html.markdown new file mode 100644 index 00000000..7f698f09 --- /dev/null +++ b/de-de/scala-de.html.markdown @@ -0,0 +1,810 @@ +--- +language: Scala +contributors: + - ["George Petrov", "http://github.com/petrovg"] + - ["Dominic Bou-Samra", "http://dbousamra.github.com"] + - ["Geoff Liu", "http://geoffliu.me"] + - ["Ha-Duong Nguyen", "http://reference-error.org"] +translators: + - ["Christian Albrecht", "https://github.com/coastalchief"] +filename: scala-de.html.markdown +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 +der EPFL (Lausanne / Schweiz) unter der Leitung von Martin Odersky entwickelt. + + +# 0. 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 +4. Mit dem Kommando `scala` wird die REPL gestartet und zeigt als Prompt: +``` +scala> +``` + +Die REPL (Read-Eval-Print Loop) ist der interaktive Scala Interpreter. +Hier kann man jeden Scala Ausdruck verwenden und das Ergebnis wird direkt +ausgegeben. +Als nächstes beschäftigen wir uns mit ein paar Scala Basics. + +# 1. Basics + +Einzeilige Kommentare beginnen mit zwei vorwärts Slash + +/* + Mehrzeilige Kommentare, werden starten + mit Slash-Stern und enden mit Stern-Slash +*/ + +// Einen Wert, und eine zusätzliche neue Zeile ausgeben +``` +println("Hello world!") +println(10) +``` + +// Einen Wert, ohne eine zusätzliche neue Zeile ausgeben +``` +print("Hello world") +``` + +// Variablen werden entweder mit var oder val deklariert. +// Deklarationen mit val sind immutable, also unveränderlich +// Deklarationen mit var sind mutable, also veränderlich +// Immutability ist gut. +``` +val x = 10 // x ist 10 +x = 20 // error: reassignment to val +var y = 10 +y = 20 // y ist jetzt 20 +``` + +Scala ist eine statisch getypte Sprache, auch wenn in dem o.g. Beispiel +keine Typen an x und y geschrieben haben. +In Scala ist etwas eingebaut, was sich Type Inference nennt. D.h. das der +Scala Compiler in den meisten Fällen erraten kann, von welchen Typ eine ist, +so dass der Typ nicht jedes mal angegeben werden soll. +Einen Typ gibt man bei einer Variablendeklaration wie folgt an: +``` +val z: Int = 10 +val a: Double = 1.0 +``` + +// Bei automatischer Umwandlung von Int auf Double wird aus 10 eine 10.0 +``` +val b: Double = 10 +``` + +// Boolean Werte +``` +true +false +``` + +// Boolean Operationen +``` +!true // false +!false // true +true == false // false +10 > 5 // true +``` + +// Mathematische Operationen sind wie gewohnt +``` +1 + 1 // 2 +2 - 1 // 1 +5 * 3 // 15 +6 / 2 // 3 +6 / 4 // 1 +6.0 / 4 // 1.5 +``` + +// Die Auswertung eines Ausdrucks in der REPL gibt den Typ +// und das Ergebnis zurück. +``` + scala> 1 + 7 + res29: Int = 8 +``` + +Das bedeutet, dass das Resultat der Auswertung von 1 + 7 ein Objekt +von Typ Int ist und einen Wert 0 hat. +"res29" ist ein sequentiell generierter name, um das Ergebnis des +Ausdrucks zu speichern. Dieser Wert kann bei Dir anders sein... + + +"Scala strings werden in doppelten Anführungszeichen eingeschlossen" +'a' // A Scala Char +// 'Einzeln ge-quotete strings gibt es nicht!' <= This causes an error + +// Für Strings gibt es die üblichen Java Methoden +``` +"hello world".length +"hello world".substring(2, 6) +"hello world".replace("C", "3") +``` + +// Zusätzlich gibt es noch extra Scala Methoden +// siehe: scala.collection.immutable.StringOps +``` +"hello world".take(5) +"hello world".drop(5) +``` + +// String interpolation: prefix "s" +``` +val n = 45 +s"We have $n apples" // => "We have 45 apples" +``` + +// Ausdrücke im innern von interpolierten Strings gibt es auch +``` +val a = Array(11, 9, 6) +val n = 100 +s"My second daughter is ${a(0) - a(2)} years old." // => "My second daughter is 5 years old." +s"We have double the amount of ${n / 2.0} in apples." // => "We have double the amount of 22.5 in apples." +s"Power of 2: ${math.pow(2, 2)}" // => "Power of 2: 4" +``` + +// Formatierung der interpolierten Strings mit dem prefix "f" +``` +f"Power of 5: ${math.pow(5, 2)}%1.0f" // "Power of 5: 25" +f"Square root of 122: ${math.sqrt(122)}%1.4f" // "Square root of 122: 11.0454" +``` + +// Raw Strings, ignorieren Sonderzeichen. +``` +raw"New line feed: \n. Carriage return: \r." // => "New line feed: \n. Carriage return: \r." +``` + +// Manche Zeichen müssen "escaped" werden, z.B. +// ein doppeltes Anführungszeichen in innern eines Strings. +``` +"They stood outside the \"Rose and Crown\"" // => "They stood outside the "Rose and Crown"" +``` + +// Dreifache Anführungszeichen erlauben es, dass ein String über mehrere Zeilen geht +// und Anführungszeichen enthalten kann. +``` +val html = """
+

Press belo', Joe

+ +
""" +``` + +# 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. +``` +def sumOfSquares(x: Int, y: Int): Int = { + val x2 = x * x + val y2 = y * y + x2 + y2 +} +``` + +// Die geschweiften Klammern können weggelassen werden, wenn +// die Funktion nur aus einem einzigen Ausdruck besteht: +``` +def sumOfSquaresShort(x: Int, y: Int): Int = x * x + y * y +``` + +// Syntax für Funktionsaufrufe: +``` +sumOfSquares(3, 4) // => 25 +``` + +// In den meisten Fällen (mit Ausnahme von rekursiven Funktionen), können +// Rückgabetypen auch weggelassen werden, da dieselbe Typ Inference, wie bei +// Variablen, auch bei Funktionen greift: +``` +def sq(x: Int) = x * x // Compiler errät, dass der return type Int ist +``` + +// Funktionen können default parameter haben: +``` +def addWithDefault(x: Int, y: Int = 5) = x + y +addWithDefault(1, 2) // => 3 +addWithDefault(1) // => 6 +``` + +// Anonyme Funktionen sehen so aus: +``` +(x: Int) => x * x +``` + +// Im Gegensatz zu def bei normalen Funktionen, kann bei anonymen Funktionen +// sogar der Eingabetyp weggelassen werden, wenn der Kontext klar ist. +// Beachte den Typ "Int => Int", dies beschreibt eine Funktion, +// welche Int als Parameter erwartet und Int zurückgibt. +``` +val sq: Int => Int = x => x * x +``` + +// Anonyme Funktionen benutzt man ganz normal: +``` +sq(10) // => 100 +``` + +// Wenn ein Parameter einer anonymen Funktion nur einmal verwendet wird, +// bietet Scala einen sehr kurzen Weg diesen Parameter zu benutzen, +// indem die Parameter als Unterstrich "_" in der Parameterreihenfolge +// verwendet werden. Diese anonymen Funktionen werden sehr häufig +// verwendet. +``` +val addOne: Int => Int = _ + 1 +val weirdSum: (Int, Int) => Int = (_ * 2 + _ * 3) +addOne(5) // => 6 +weirdSum(2, 4) // => 16 +``` + +// Es gibt einen keyword return in Scala. Allerdings ist seine Verwendung +// nicht immer ratsam und kann fehlerbehaftet sein. "return" gibt nur aus +// dem innersten def, welches den return Ausdruck umgibt, zurück. +// "return" hat keinen Effekt in anonymen Funktionen: +``` +def foo(x: Int): Int = { + val anonFunc: Int => Int = { z => + if (z > 5) + 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 + +## Wertebereiche und Schleifen +``` +1 to 5 +val r = 1 to 5 +r.foreach(println) +r foreach println +(5 to 1 by -1) foreach (println) +``` +// Scala ist syntaktisch sehr grosszügig, Semikolons am Zeilenende +// 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. + +// Ein do while Schleife +``` +do { + println("x is still less than 10") + x += 1 +} while (x < 10) +``` + +// Endrekursionen sind ideomatisch um sich wiederholende +// Dinge in Scala zu lösen. Rekursive Funtionen benötigen explizit einen +// return Typ, der Compiler kann ihn nicht erraten. +// Unit, in diesem Beispiel. +``` +def showNumbersInRange(a: Int, b: Int): Unit = { + print(a) + if (a < b) + showNumbersInRange(a + 1, b) +} +showNumbersInRange(1, 14) +``` + +## Conditionals +``` +val x = 10 +if (x == 1) println("yeah") +if (x == 10) println("yeah") +if (x == 11) println("yeah") +if (x == 11) println ("yeah") else println("nay") +println(if (x == 10) "yeah" else "nope") +val text = if (x == 10) "yeah" else "nope" +``` + +# 4. Daten Strukturen (Array, Map, Set, Tuples) + +## Array +``` +val a = Array(1, 2, 3, 5, 8, 13) +a(0) +a(3) +a(21) // Exception +``` + +## Map - Speichert Key-Value-Paare +``` +val m = Map("fork" -> "tenedor", "spoon" -> "cuchara", "knife" -> "cuchillo") +m("fork") +m("spoon") +m("bottle") // Exception +val safeM = m.withDefaultValue("no lo se") +safeM("bottle") +``` +## Set - Speichert Unikate, unsortiert (sortiert -> SortedSet) +``` +val s = Set(1, 3, 7) +s(0) //false +s(1) //true +val s = Set(1,1,3,3,7) +s: scala.collection.immutable.Set[Int] = Set(1, 3, 7) +``` +## Tuple - Speichert beliebige Daten und "verbindet" sie miteinander +// Ein Tuple ist keine Collection. +``` +(1, 2) +(4, 3, 2) +(1, 2, "three") +(a, 2, "three") +``` + +// Hier ist der Rückgabewert der Funktion ein Tuple +// Die Funktion gibt das Ergebnis, so wie den Rest zurück. +``` +val divideInts = (x: Int, y: Int) => (x / y, x % y) +divideInts(10, 3) +``` + +// Um die Elemente eines Tuples anzusprechen, benutzt man diese +// Notation: _._n wobei n der index des Elements ist (Index startet bei 1) +``` +val d = divideInts(10, 3) +d._1 +d._2 +``` +# 5. Objekt Orientierte Programmierung + +Bislang waren alle gezeigten Sprachelemente einfache Ausdrücke, welche zwar +zum Ausprobieren und Lernen in der REPL gut geeignet sind, jedoch in +einem Scala file selten alleine zu finden sind. +Die einzigen Top-Level Konstrukte in Scala sind nämlich: + +- Klassen (classes) +- Objekte (objects) +- case classes +- traits + +Diesen Sprachelemente wenden wir uns jetzt zu. + +## Klassen + +// Zum Erstellen von Objekten benötigt man eine Klasse, wie in vielen +// anderen Sprachen auch. + +// erzeugt Klasse mit default Konstruktor +``` +class Hund +scala> val t = new Hund +t: Hund = Hund@7103745 +``` + +// Der Konstruktor wird direkt hinter dem Klassennamen deklariert. +``` +class Hund(sorte: String) +scala> val t = new Hund("Dackel") +t: Hund = Hund@14be750c +scala> t.sorte //error: value sorte is not a member of Hund +``` + +// Per val wird aus dem Attribut ein unveränderliches Feld der Klasse +// Per var wird aus dem Attribut ein veränderliches Feld der Klasse +``` +class Hund(val sorte: String) +scala> val t = new Hund("Dackel") +t: Hund = Hund@74a85515 +scala> t.sorte +res18: String = Dackel +``` + +// Methoden werden mit def geschrieben +``` +def bark = "Woof, woof!" +``` + +// Felder und Methoden können public, protected und private sein +// default ist public +// private ist nur innerhalb des deklarierten Bereichs sichtbar +``` +class Hund { + private def x = ... + def y = ... +} +``` + +// protected ist nur innerhalb des deklarierten und aller +// erbenden Bereiche sichtbar +``` +class Hund { + protected def x = ... +} +class Dackel extends Hund { + // x ist sichtbar +} +``` +## Object +Wird ein Objekt ohne das Schlüsselwort "new" instanziert, wird das sog. +"companion object" aufgerufen. Mit dem "object" Schlüsselwort wird so +ein Objekt (Typ UND Singleton) erstellt. Damit kann man dann eine Klasse +benutzen ohne ein Objekt instanziieren zu müssen. +Ein gültiges companion Objekt einer Klasse ist es aber erst dann, wenn +es genauso heisst und in derselben Datei wie die Klasse definiert wurde. +``` +object Hund { + def alleSorten = List("Pitbull", "Dackel", "Retriever") + def createHund(sorte: String) = new Hund(sorte) +} +``` +## Case classes +Fallklassen bzw. Case classes sind Klassen die normale Klassen um extra +Funktionalität erweitern. Mit Case Klassen bekommt man ein paar +Dinge einfach dazu, ohne sich darum kümmern zu müssen. Z.B. +ein companion object mit den entsprechenden Methoden, +Hilfsmethoden wie toString(), equals() und hashCode() und auch noch +Getter für unsere Attribute (das Angeben von val entfällt dadurch) +``` +class Person(val name: String) +class Hund(val sorte: String, val farbe: String, val halter: Person) +``` + +// Es genügt das Schlüsselwort case vor die Klasse zu schreiben. +``` +case class Person(name: String) +case class Hund(sorte: String, farbe: String, halter: Person) +``` + +// Für neue Instanzen brauch man kein "new" +``` +val dackel = Hund("dackel", "grau", Person("peter")) +val dogge = Hund("dogge", "grau", Person("peter")) + +``` +// getter +``` +dackel.halter // => Person = Person(peter) +``` + +// equals +``` +dogge == dackel // => false +``` + +// copy +// otherGeorge == Person("george", "9876") +``` +val otherGeorge = george.copy(phoneNumber = "9876") +``` +## Traits +Ähnlich wie Java interfaces, definiert man mit traits einen Objekttyp +und Methodensignaturen. Scala erlaubt allerdings das teilweise +implementieren dieser Methoden. Konstruktorparameter sind nicht erlaubt. +Traits können von anderen Traits oder Klassen erben, aber nur von +parameterlosen. +``` +trait Hund { + def sorte: String + def farbe: String + def bellen: Boolean = true + def beissen: Boolean +} +class Bernhardiner extends Hund{ + val sorte = "Bernhardiner" + val farbe = "braun" + 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 +``` + +// Traits können auch via Mixins (Schlüsselwort "with") eingebunden werden +``` +trait Bellen { + def bellen: String = "Woof" +} +trait Hund { + def sorte: String + def farbe: String +} +class Bernhardiner extends Hund with Bellen{ + val sorte = "Bernhardiner" + val farbe = "braun" +} +scala> val b = new Bernhardiner +b: Bernhardiner = Bernhardiner@7b69c6ba +scala> b.bellen +res0: String = Woof +``` + +# 6. Pattern Matching +Pattern matching in Scala ist ein sehr nützliches und wesentlich +mächtigeres Feature als Vergleichsfunktionen in Java. In Scala +benötigt ein case Statement kein "break", ein fall-through gibt es nicht. +Mehrere Überprüfungen können mit einem Statement gemacht werden. +Pattern matching wird mit dem Schlüsselwort "match" gemacht. +``` +val x = ... +x match { + case 2 => + case 3 => + case _ => +} +``` + +// Pattern Matching kann auf beliebige Typen prüfen +``` +val any: Any = ... +val gleicht = any match { + case 2 | 3 | 5 => "Zahl" + case "woof" => "String" + case true | false => "Boolean" + case 45.35 => "Double" + case _ => "Unbekannt" +} +``` + +// und auf Objektgleichheit +``` +def matchPerson(person: Person): String = person match { + case Person("George", nummer) => "George! Die Nummer ist " + number + case Person("Kate", nummer) => "Kate! Die Nummer ist " + nummer + case Person(name, nummer) => "Irgendjemand: " + name + ", Telefon: " + nummer +} +``` + +// Und viele mehr... +``` +val email = "(.*)@(.*)".r // regex +def matchEverything(obj: Any): String = obj match { + // Werte: + case "Hello world" => "Got the string Hello world" + // 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!" + // 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" + // 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" +} +``` + +// Jedes Objekt mit einer "unapply" Methode kann per Pattern geprüft werden +// Ganze Funktionen können Patterns sein +``` +val patternFunc: Person => String = { + case Person("George", number) => s"George's number: $number" + case Person(name, number) => s"Random person's number: $number" +} +``` + +# 7. Higher-order functions +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" + +## List +``` +def isGleichVier(a:Int) = a == 4 +val list = List(1, 2, 3, 4) +val resultExists4 = list.exists(isEqualToFour) +``` + +## map +// map nimmt eine Funktion und führt sie auf jedem Element aus und erzeugt +// eine neue Liste + +// Funktion erwartet ein Int und returned ein Int +``` +val add10: Int => Int = _ + 10 +``` + +// add10 wird auf jedes Element angewendet +``` +List(1, 2, 3) map add10 // => List(11, 12, 13) +``` + +// Anonyme Funktionen können anstatt definierter Funktionen verwendet werden +``` +List(1, 2, 3) map (x => x + 10) +``` + +// Der Unterstrich wird anstelle eines Parameters einer anonymen Funktion +// verwendet. Er wird an die Variable gebunden. +``` +List(1, 2, 3) map (_ + 10) +``` + +// Wenn der anonyme Block und die Funtion beide EIN Argument erwarten, +// kann sogar der Unterstrich weggelassen werden. +``` +List("Dom", "Bob", "Natalia") foreach println +``` + +## filter +// filter nimmt ein Prädikat (eine Funktion von A -> Boolean) und findet +// alle Elemente die auf das Prädikat passen +``` +List(1, 2, 3) filter (_ > 2) // => List(3) +case class Person(name: String, age: Int) +List( + Person(name = "Dom", age = 23), + Person(name = "Bob", age = 30) +).filter(_.age > 25) // List(Person("Bob", 30)) +``` + +## reduce +// reduce nimmt zwei Elemente und kombiniert sie zu einem Element, +// und zwar solange bis nur noch ein Element da ist. + +## foreach +// foreach gibt es für einige Collections +``` +val aListOfNumbers = List(1, 2, 3, 4, 10, 20, 100) +aListOfNumbers foreach (x => println(x)) +aListOfNumbers foreach println +``` +## For comprehensions +// Eine for-comprehension definiert eine Beziehung zwischen zwei Datensets. +// Dies ist keine for-Schleife. +``` +for { n <- s } yield sq(n) +val nSquared2 = for { n <- s } yield sq(n) +for { n <- nSquared2 if n < 10 } yield n +for { n <- s; nSquared = n * n if nSquared < 10} yield nSquared +``` + +///////////////////////////////////////////////// +# 8. Implicits +///////////////////////////////////////////////// + +**ACHTUNG:** +Implicits sind ein sehr mächtiges Sprachfeature von Scala. Es sehr einfach +sie falsch zu benutzen und Anfänger sollten sie mit Vorsicht oder am +besten erst dann benutzen, wenn man versteht wie sie funktionieren. +Dieses Tutorial enthält Implicits, da sie in Scala an jeder Stelle +vorkommen und man auch mit einer Lib die Implicits benutzt nichts sinnvolles +machen kann. +Hier soll ein Grundverständnis geschaffen werden, wie sie funktionieren. + +// Mit dem Schlüsselwort implicit können Methoden, Werte, Funktion, Objekte +// zu "implicit Methods" werden. +``` +implicit val myImplicitInt = 100 +implicit def myImplicitFunction(sorte: String) = new Hund("Golden " + sorte) +``` + +// implicit ändert nicht das Verhalten eines Wertes oder einer Funktion +``` +myImplicitInt + 2 // => 102 +myImplicitFunction("Pitbull").sorte // => "Golden Pitbull" +``` + +// Der Unterschied ist, dass diese Werte ausgewählt werden können, wenn ein +// anderer Codeteil einen implicit Wert benötigt, zum Beispiel innerhalb von +// implicit Funktionsparametern + +// Diese Funktion hat zwei Parameter: einen normalen und einen implicit +``` +def sendGreetings(toWhom: String)(implicit howMany: Int) = + s"Hello $toWhom, $howMany blessings to you and yours!" +``` + +// Werden beide Parameter gefüllt, verhält sich die Funktion wie erwartet +``` +sendGreetings("John")(1000) // => "Hello John, 1000 blessings to you and yours!" +``` + +// Wird der implicit Parameter jedoch weggelassen, wird ein anderer +// implicit Wert vom gleichen Typ genommen. Der Compiler sucht im +// 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 +``` +sendGreetings("Jane") // => "Hello Jane, 100 blessings to you and yours!" +``` + +// bzw. "myImplicitFunction" +// Der String wird erst mit Hilfe der Funktion in Hund konvertiert, und +// dann wird die Methode aufgerufen +``` +"Retriever".sorte // => "Golden Retriever" +``` + +# 9. Misc +## Importe +``` +import scala.collection.immutable.List +``` + +// Importiere alle Unterpackages +``` +import scala.collection.immutable._ +``` + +// Importiere verschiedene Klassen mit einem Statement +``` +import scala.collection.immutable.{List, Map} +``` + +// Einen Import kann man mit '=>' umbenennen +``` +import scala.collection.immutable.{List => ImmutableList} +``` + +// Importiere alle Klasses, mit Ausnahem von.... +// Hier ohne: Map and Set: +``` +import scala.collection.immutable.{Map => _, Set => _, _} +``` +## Main +``` +object Application { + def main(args: Array[String]): Unit = { + // stuff goes here. + } +} +``` + +## I/O +// Eine Datei Zeile für Zeile lesen +``` +import scala.io.Source +for(line <- Source.fromFile("myfile.txt").getLines()) + println(line) +``` + +// Eine Datei schreiben +``` +val writer = new PrintWriter("myfile.txt") +writer.write("Writing line for line" + util.Properties.lineSeparator) +writer.write("Another line here" + util.Properties.lineSeparator) +writer.close() +``` + +## Further resources + +* [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/) +* [Try Scala in your browser](http://scalatutorials.com/tour/) +* Join the [Scala user group](https://groups.google.com/forum/#!forum/scala-user) \ No newline at end of file -- cgit v1.2.3 From d7e2f6e12adc4f174138dbb95470f184c4b71131 Mon Sep 17 00:00:00 2001 From: Christian Albrecht Date: Fri, 16 Oct 2015 19:09:14 +0200 Subject: ruby translation in german --- de-de/ruby-de.html.markdown | 611 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 611 insertions(+) create mode 100644 de-de/ruby-de.html.markdown diff --git a/de-de/ruby-de.html.markdown b/de-de/ruby-de.html.markdown new file mode 100644 index 00000000..4815fa40 --- /dev/null +++ b/de-de/ruby-de.html.markdown @@ -0,0 +1,611 @@ +--- +language: ruby +contributors: + - ["David Underwood", "http://theflyingdeveloper.com"] + - ["Joel Walden", "http://joelwalden.net"] + - ["Luke Holder", "http://twitter.com/lukeholder"] + - ["Tristan Hume", "http://thume.ca/"] + - ["Nick LaMuro", "https://github.com/NickLaMuro"] + - ["Marcos Brizeno", "http://www.about.me/marcosbrizeno"] + - ["Ariel Krakowski", "http://www.learneroo.com"] + - ["Dzianis Dashkevich", "https://github.com/dskecse"] + - ["Levi Bostian", "https://github.com/levibostian"] + - ["Rahil Momin", "https://github.com/iamrahil"] +translators: + - ["Christian Albrecht", "https://github.com/coastalchief"] +filename: ruby-de.html.markdown +lang: de-de +--- + +# Dies ist ein Kommentar + +=begin +Dies sind multi-line +Kommentare. Niemand benutzt +die wirklich. +=end + +# Objekte - Alles ist ein Objekt + +## Zahlen sind Objekte +``` +3.class #=> Fixnum +3.to_s #=> "3" +``` + +### Simple Arithmetik +``` +1 + 1 #=> 2 +8 - 1 #=> 7 +10 * 2 #=> 20 +35 / 5 #=> 7 +2**5 #=> 32 +``` + +// Arithmetik ist aber eigentlich nur syntaktischer Zucker +// um eine Methode eines Objekt aufzurufen +``` +1.+(3) #=> 4 +10.* 5 #=> 50 +``` + +## Special values sind Objekte +``` +nil # Nothing to see here +true # truth +false # falsehood + +nil.class #=> NilClass +true.class #=> TrueClass +false.class #=> FalseClass +``` + +## Objektvergleiche +### Gleicheit +``` +1 == 1 #=> true +2 == 1 #=> false +``` +### Ungleichheit +``` +1 != 1 #=> false +2 != 1 #=> true +``` +### Neben false selbst, nil ist ein anderer 'falsey' Wert +``` +!nil #=> true +!false #=> true +!0 #=> false +``` +### Weitere Vergleiche +``` +1 < 10 #=> true +1 > 10 #=> false +2 <= 2 #=> true +2 >= 2 #=> true +``` +### 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. + +#### and +##### `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. +do_something() or log_error() + +## Strings sind Objekte +``` +'I am a string'.class #=> String +"I am a string too".class #=> String + + +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. + +### 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 +``` +x = y = 10 #=> 10 +x #=> 10 +y #=> 10 +``` +## Benennung +### Konvention ist snake_case +``` +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. + +``` +:pending.class #=> Symbol +status = :pending +status == :pending #=> true +status == 'pending' #=> false +status == :approved #=> false +``` +# Arrays + +## Ein Array anlegen +``` +array = [1, 2, 3, 4, 5] #=> [1, 2, 3, 4, 5] +``` + +## 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önnen von vorne indiziert werden +``` +array[0] #=> 1 +array[12] #=> nil +``` + +## Arrays können von hinten indiziert werden +``` +array[-1] #=> 5 +``` + +## Arrays können mit Stard Index und Länge indiziert werden +``` +array[2, 3] #=> [3, 4, 5] +``` + +## Arrays können mit einer Range indiziert werden +``` +array[1..3] #=> [2, 3, 4] +``` + +## Einen Wert hinzufügen +``` +array << 6 #=> [1, 2, 3, 4, 5, 6] +array.push(6) #=> [1, 2, 3, 4, 5, 6] +``` + +## Testen, ob ein Element schon vorhanden ist +``` +array.include?(1) #=> true +``` + +# Hashes +Hashes sind das Hauptfeature um Key/Values zu speichern + +``` + +## Ein Hash anlegen +``` +hash = { 'color' => 'green', 'number' => 5 } +hash.keys #=> ['color', 'number'] +``` + +## Wert per key herausfinden +``` +hash['color'] #=> 'green' +hash['number'] #=> 5 +hash['nothing here'] #=> nil +// Asking a hash for a key that doesn't exist returns nil: +``` + +## Symbols können auch keys sein +``` +new_hash = { defcon: 3, action: true } +new_hash.keys #=> [:defcon, :action] +``` + +## Testen ob ein Key oder ein Value existiert +``` +new_hash.has_key?(:defcon) #=> true +new_hash.has_value?(3) #=> true +``` + +### Tip: Arrays und Hashes sind Enumerable +### Und haben gemeinsame, hilfreiche Methoden wie: +### each, map, count, and more + +# Kontrolstrukturen +## if +``` +if true + 'if statement' +elsif false + 'else if, optional' +else + 'else, also 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. + +``` +(1..5).each do |counter| + puts "iteration #{counter}" +end +``` + +Die each Methode einer Range führt den Block für jedes Element der Range aus. + +Dem Block wird ein "counter" parameter übergeben. + +### Den Block kann man auch in geschweiften Klammern schreiben +``` +(1..5).each { |counter| puts "iteration #{counter}" } +``` + +### Each kann auch über den Inhalt von Datenstrukturen iterieren +``` +array.each do |element| + puts "#{element} is part of the array" +end +hash.each do |key, value| + puts "#{key} is #{value}" +end + +counter = 1 +while counter <= 5 do + puts "iteration #{counter}" + counter += 1 +end +``` + +## case +``` +grade = 'B' + +case grade +when 'A' + puts 'Way to go kiddo' +when 'B' + puts 'Better luck next time' +when 'C' + puts 'You can do better' +when 'D' + puts 'Scraping through' +when 'F' + puts 'You failed!' +else + puts 'Alternative grading system, eh?' +end +=> "Better luck next time" +``` + +### Case können auch ranges +``` +grade = 82 +case grade +when 90..100 + puts 'Hooray!' +when 80...90 + puts 'OK job' +else + puts 'You failed!' +end +=> "OK job" +``` + +# exception handling: +``` +begin + # code here that might raise an exception + raise NoMemoryError, 'You ran out of memory.' +rescue NoMemoryError => exception_variable + puts 'NoMemoryError was raised', exception_variable +rescue RuntimeError => other_exception_variable + puts 'RuntimeError was raised now' +else + puts 'This runs if no exceptions were thrown at all' +ensure + puts 'This code always runs no matter what' +end +``` +# Funktionen +``` +def double(x) + x * 2 +end +``` +## Funktionen (und Blocks) +## geben implizit den Wert des letzten Statements zurück +``` +double(2) #=> 4 +``` + +### Klammern sind optional wenn das Ergebnis nicht mehdeutig ist +``` +double 3 #=> 6 +double double 3 #=> 12 +def sum(x, y) + x + y +end +``` + +### Methoden Parameter werden per 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 +``` +def surround + puts '{' + yield + puts '}' +end +surround { puts 'hello world' } +``` + +## Einen Block kann man auch einer Methoden übergeben +### "&" kennzeichnet die Referenz zum übergebenen Block +``` +def guests(&block) + block.call 'some_argument' +end +``` + +### Eine Liste von Parametern kann man auch übergeben, +### Diese wird in ein Array konvertiert +### "*" kennzeichnet dies. +``` +def guests(*array) + array.each { |guest| puts guest } +end +``` +# Klassen +## Werden mit dem class Schlüsselwort definiert +``` +class Human +``` + +### Konstruktor bzw. Initializer +``` + def initialize(name, age = 0) + # Assign the argument to the "name" instance variable for the instance + @name = name + # If no age given, we will fall back to the default in the arguments list. + @age = age + end +``` + +### setter Methode +``` + def name=(name) + @name = name + end +``` +### getter Methode +``` + def name + @name + end +``` + +#### getter können mit der attr_accessor Methode vereinfacht definiert werden +``` + attr_accessor :name + # Getter/setter methods can also be created individually like this + 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. + def self.say(msg) + puts msg + end + def species + @@species + end +end +``` + +## Eine Klasse instanziieren +``` +jim = Human.new('Jim Halpert') +dwight = Human.new('Dwight K. Schrute') +``` + +## Methodenaufrufe +``` +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 +``` +Human.say('Hi') #=> "Hi" +``` + +## Variable Gültigkeit +### Variablen die mit "$" starten, gelten global +``` +$var = "I'm a global var" +defined? $var #=> "global-variable" +``` + +### Variablen die mit "@" starten, gelten für die Instanz +``` +@var = "I'm an instance var" +defined? @var #=> "instance-variable" +``` + +### Variablen die mit "@@" starten, gelten für die Klasse +``` +@@var = "I'm a class var" +defined? @@var #=> "class variable" +``` + +### Variablen die mit einem Großbuchstaben anfangen, sind Konstanten +``` +Var = "I'm a constant" +defined? Var #=> "constant" +``` + +## Class ist auch ein Objekt +### Hat also auch Instanzvariablen +### Eine Klassenvariable wird innerhalb der Klasse und Ableitungen geteilt. + +### Basis Klasse +``` +class Human + @@foo = 0 + def self.foo + @@foo + end + def self.foo=(value) + @@foo = value + end +end +``` + +### Abgeleitete Klasse +``` +class Worker < Human +end +Human.foo # 0 +Worker.foo # 0 +Human.foo = 2 # 2 +Worker.foo # 2 +``` + +### Eine Klasseninstanzvariable wird nicht geteilt +``` +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 +``` +``` +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 +``` +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 + end + 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' +``` + +## Additional resources + +- [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/) +- [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. -- cgit v1.2.3 From 8811b18ef864b2cdca5b7a4d925a875ac4124884 Mon Sep 17 00:00:00 2001 From: Christian Albrecht Date: Fri, 16 Oct 2015 20:19:51 +0200 Subject: ruby ecosystem translation to german --- de-de/ruby-ecosystem-de.html.markdown | 149 ++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 de-de/ruby-ecosystem-de.html.markdown diff --git a/de-de/ruby-ecosystem-de.html.markdown b/de-de/ruby-ecosystem-de.html.markdown new file mode 100644 index 00000000..e1f3c5e7 --- /dev/null +++ b/de-de/ruby-ecosystem-de.html.markdown @@ -0,0 +1,149 @@ +--- +category: tool +tool: ruby ecosystem +contributors: + - ["Jon Smock", "http://github.com/jonsmock"] + - ["Rafal Chmiel", "http://github.com/rafalchmiel"] +translators: + - ["Christian Albrecht", "https://github.com/coastalchief"] +filename: ruby-ecosystem-de.html.markdown +lang: de-de +--- + +Hier gibt es einen Überblick über die gängigsten Tools zur Verwaltung +von verschiedenen Ruby Versionen, Gems und Dependencies. + +## Ruby Managers + +Einige Betriebssysteme haben bereits eine Ruby Version vorinstalliert +oder bieten sie als Package zum Download an. Die meisten Rubyisten +benutzen diese aber eher nicht und wenn, dann um damit einen Ruby +Manager zu installieren. Damit kann man komfortabel zwischen den +verschiedenen Versionen hin und herspringen. + +Dies sind die beliebtesten: + +* [RVM](https://rvm.io/) - Installiert und wechselt zwischen rubies + RVM kennt verschiedene Ruby Versionen und hat das Konzept der gemsets, + um gem Abhängigkeiten pro Projekt zu managen. +* [ruby-build](https://github.com/sstephenson/ruby-build) + Installiert nur rubies, kann diese aber sehr gut verwalten +* [rbenv](https://github.com/sstephenson/rbenv) - Wechselt Ruby Versionen. + Wird zusammen mit ruby-build benutzt. Hiermit kann man kontrollieren, + wie rubies laden. +* [chruby](https://github.com/postmodern/chruby) - Wechselt Ruby Versionen. + Ähnlich rbenv. + +## Ruby Versionen + +Ruby wurde von Yukihiro "Matz" Matsumoto vor gut 20 Jahren veröffentlicht. +Matz ist nach wie vor in die Entwicklung involviert. Daher kommt auch der +Name der Referenzimplementierung: MRI (Matz' Reference Implementation). + +Die aktuellste Version ist **2.2.3** und wurde im August 2015 veröffentlicht! + +Hier eine kurze Versionshistorie: + +* 2.0.0 - Release im Februar 2013 -- Release zum 20. Geburtstag der Sprache + [Rubies are forever](http://www.heise.de/developer/artikel/Ruby-2-0-als-Geschenk-zum-20-Geburtstag-1808109.html) +* 1.9.3 - Release im Oktober 2011 + [End of Life](https://www.ruby-lang.org/en/news/2015/02/23/support-for-ruby-1-9-3-has-ended/) +* 1.8.7 - Release im Juni 2006 + [End of Life](http://www.ruby-lang.org/en/news/2013/06/30/we-retire-1-8-7/). + +Die Veränderung zwischen 1.8.7 und 1.9.x war sehr groß und eine Migration +nicht so einfach möglich. Der Versionssprung auf 2.0.0 war verglichen dazu +weit weniger dramatisch. +Beispielsweise hat 1.9. Encodings und eine Bytecode VM eingeführt. +Es gibt immer noch Projekte die auf der stabilen Version 1.8.7 laufen, +aber diese sind mittlerweile in der Minderheit. Die meisten Projekte +laufen auf 1.9.x oder auf 2.x. + +## Ruby Implementierungen + +Das Ruby Ecosystem beinhaltet viele verschiedene Implementierungen von Ruby, +jedes mit seinen eigenen Vorteilen und verschiedenen Graden von +Kompatibilität. Auch wenn alle diese Implementierungen in verschiedenen +Sprachen geschrieben sind, sind sie doch **alle Ruby**. +Jede Implementierung bietet neben ihren speziellen Features immer auch +die Möglichkeit normale ruby Dateien auszuführen. + +Am ausgereiftesten und stabilsten: + +* [MRI](https://github.com/ruby/ruby) - Geschrieben in C, das ist die Referenz Implementierung. + Sie ist 100% kompatibel (mit sich selbst ;-). Alle anderen rubies + bleiben kompatibel mit MRI (siehe [RubySpec](#rubyspec) weiter unten). +* [JRuby](http://jruby.org/) - Geschrieben in Java and Ruby, Robust und ziemlich schnell. + Der größte Vorteil von JRuby ist die Interoperabilität mit JVM/Java und damit die + Benutzung von Ruby im Java Ecosystem. +* [Rubinius](http://rubini.us/) - Geschrieben in Ruby mit C++ bytecode VM. + Auch sehr ausgereift und schnell. + +Mittel ausgereift / kompatibel: + +* [Maglev](http://maglev.github.io/) - Baut auf Gemstone, ein Smalltalk VM. + Dieses Projekt versucht das großartige Smalltalk Tooling in die Ruby Welt + zu bringen. +* [RubyMotion](http://www.rubymotion.com/) - Ruby in der iOS Entwicklung. + +Weniger ausgereift/kompatibel: + +* [Topaz](http://topazruby.com/) - Geschrieben in RPython (via PyPy) + Topaz ist noch ziemlich jung und versucht die schnellste Implementierung + zu werden. +* [IronRuby](http://ironruby.net/) - Geschrieben in C# für die .NET Plaftform + Das letzte Release von IronRuby ist mittlerweile 5 Jahre her. + +Die Ruby Implementierungen haben ihre eigenen Versionsnummern, sind aber +trotzdem immer zu einer MRI Version kompatibel. +Viele können sogar zwischen verschiedenen Modi wechseln (1.8 mode -> 1.9 mode) + +## RubySpec + +Die meisten Ruby Implementierungen vertrauen der [RubySpec](http://rubyspec.org/). +sehr stark. Da Ruby keine offizielle Spezifikation hat, hat die +Community ausführbare Specs (in Ruby) geschrieben, um so die Kompatibilität +zur MRI testen zu können. + +## RubyGems + +[RubyGems](http://rubygems.org/) ist der Community Paket Manager von Ruby. +RubyGems kommt mit Ruby zusammen, so dass kein extra Tool nötig ist. + +Ruby Pakete werden "gems" genannt und könnten auf RubyGems.org +veröffentlicht werden. Jedes Gem enthält den Source Code und Meta Daten, +wie die Versionsnummer, weitere Abhängigkeiten, Autoren und Lizenzen. + +## Bundler + +[Bundler](http://bundler.io/) ist ein Tool um Abhängigkeiten zwischen +Gems aufzulösen und zu managen. Dazu werden diese in einem gemfile +zusammengefasst und Bundler kümmert sich darum die Abhängigkeiten +untereinander rekursiv aufzulösen. Entweder es klappt und alle gems +konnten runtergeladen werden, oder es wird abgebrochen und +der Konflikt gemeldet. +Zum Beispiel: +Wenn Gem A die Version 3 oder höher von Gem Z braucht, aber Gem B +von Gem Z die Version 2, dann ist das ein Konflikt. + +# Testing + +Test-Driven Development ist ein essentieller Teil der Ruby Kultur. +Ruby bringt sein eigenes Unit-Test framework mit, minitest. Darüberhinaus +gibt es noch viele weitere Testframeworks mit unterschiedlichsten Zielen: + +* [TestUnit](http://ruby-doc.org/stdlib-1.8.7/libdoc/test/unit/rdoc/Test/Unit.html) - Eingebaut in Ruby 1.8 + "Unit-style" Testframework +* [minitest](http://ruby-doc.org/stdlib-2.0.0/libdoc/minitest/rdoc/MiniTest.html) - Eingebaut in Ruby 1.9/2.0 + "Unit-style" Testframework +* [RSpec](http://rspec.info/) - Ein Testframework welches auf verständliche Testdefinition setzt +* [Cucumber](http://cukes.info/) - Ein BDD Testframework welches Gherkin tests parsen kann + +## Be Nice +Die Ruby Community ist stolz darauf eine offene, vielfältige und einladende +Community zu sein. Es gibt viele aktive Ruby User Gruppen und diverse +Ruby Konferenzen. Matz selbst ist so oft es geht dabei. + +* [Euruko](http://www.euruko2015.org) +* [User Groups](https://www.ruby-lang.org/de/community/user-groups/) + -- cgit v1.2.3 From 5c4d60eea88bc708748bca4589a834c356c56e4b Mon Sep 17 00:00:00 2001 From: Christian Albrecht Date: Sat, 17 Oct 2015 10:00:02 +0200 Subject: added german ressources and fixed heading --- de-de/scala-de.html.markdown | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/de-de/scala-de.html.markdown b/de-de/scala-de.html.markdown index 7f698f09..08f582cb 100644 --- a/de-de/scala-de.html.markdown +++ b/de-de/scala-de.html.markdown @@ -293,7 +293,7 @@ i // i ausgeben, res3: Int = 10 // Ein do while Schleife ``` do { - println("x is still less than 10") + println("x ist immer noch weniger wie 10") x += 1 } while (x < 10) ``` @@ -796,15 +796,21 @@ for(line <- Source.fromFile("myfile.txt").getLines()) // Eine Datei schreiben ``` val writer = new PrintWriter("myfile.txt") -writer.write("Writing line for line" + util.Properties.lineSeparator) -writer.write("Another line here" + util.Properties.lineSeparator) +writer.write("Schreibe Zeile" + util.Properties.lineSeparator) +writer.write("Und noch eine Zeile" + util.Properties.lineSeparator) writer.close() ``` -## Further resources +## Weitereführende Hinweise +// DE +* [Scala Tutorial](https://scalatutorial.wordpress.com) +* [Scala Tutorial](http://scalatutorial.de) + +// 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/) * [Try Scala in your browser](http://scalatutorials.com/tour/) +* [Neophytes Guide to Scala](http://danielwestheide.com/scala/neophytes.html) * Join the [Scala user group](https://groups.google.com/forum/#!forum/scala-user) \ No newline at end of file -- cgit v1.2.3 From 7247741e53e656a574dc7cd0e15700b9eb216cbe Mon Sep 17 00:00:00 2001 From: Christian Albrecht Date: Sat, 17 Oct 2015 14:39:21 +0200 Subject: changed heading in ruby-de --- de-de/ruby-de.html.markdown | 4 +++- de-de/scala-de.html.markdown | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/de-de/ruby-de.html.markdown b/de-de/ruby-de.html.markdown index 4815fa40..560d3958 100644 --- a/de-de/ruby-de.html.markdown +++ b/de-de/ruby-de.html.markdown @@ -602,7 +602,9 @@ Something.new.bar # => NoMethodError: undefined method `bar' Something.new.qux # => 'qux' ``` -## Additional resources +## Weiterführende Hinweise + +//EN - [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/) diff --git a/de-de/scala-de.html.markdown b/de-de/scala-de.html.markdown index 08f582cb..42808580 100644 --- a/de-de/scala-de.html.markdown +++ b/de-de/scala-de.html.markdown @@ -801,7 +801,7 @@ writer.write("Und noch eine Zeile" + util.Properties.lineSeparator) writer.close() ``` -## Weitereführende Hinweise +## Weiterführende Hinweise // DE * [Scala Tutorial](https://scalatutorial.wordpress.com) -- cgit v1.2.3