Skip to content

Commit

Permalink
Started translation (elixirschool#738)
Browse files Browse the repository at this point in the history
  • Loading branch information
Lechindianer authored and ybur-yug committed Oct 18, 2016
1 parent 122e5b5 commit 99f23a2
Show file tree
Hide file tree
Showing 20 changed files with 2,839 additions and 2 deletions.
7 changes: 6 additions & 1 deletion _config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,12 @@ description:
uk: Навчальні матеріали про мову програмування Elixir
tr: Elixir programlama dili dersleri
bg: Уроци за езика за програмиране Elixir
de: Übungen zur Programmiersprache Elixir
baseurl: /
url: https://elixirschool.com
og_image: https://elixirschool.com/assets/fb_share.jpg
permalink: pretty
languages: ['en', 'jp', 'cn', 'es', 'pt', 'vi', 'ru', 'sk', 'fr', 'gr', 'it', 'pl', 'my', 'no', 'ko', 'id', 'uk', 'tr', 'bg']
languages: ['en', 'jp', 'cn', 'es', 'pt', 'vi', 'ru', 'sk', 'fr', 'gr', 'it', 'pl', 'my', 'no', 'ko', 'id', 'uk', 'tr', 'bg', 'de']
rtl_languages: ['ar']
default_lang: en
exclude_from_localization: []
Expand All @@ -58,6 +59,7 @@ sections:
uk: Основи
tr: Temeller
bg: Основи
de: Grundlagen
- tag: advanced
label:
en: Advanced
Expand All @@ -79,6 +81,7 @@ sections:
uk: Просунуті
tr: Gelişmiş
bg: За Напреднали
de: Erweitert
- tag: specifics
label:
en: Specifics
Expand All @@ -100,6 +103,7 @@ sections:
uk: Конкретика
tr: Spesifik
bg: Спесифики
de: Einzelheiten

gems:
- kramdown
Expand Down Expand Up @@ -153,6 +157,7 @@ toc:
uk: Зміст
tr: İçerik
bg: Съдържание
de: Inhaltsverzeichnis


share:
Expand Down
24 changes: 24 additions & 0 deletions de/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
layout: page
title: Elixir School
lang: de
---

[![Lizenz](http:https://img.shields.io/badge/license-MIT-brightgreen.svg)](http:https://opensource.org/licenses/MIT)

Lektionen zur Elixir Programmiersprache, inspiriert durch Twitters [Scala School](http:https://twitter.github.io/scala_school/).

_Dein Feedback und Unterstützung ist sehr gern gesehen!_

## Über Elixir

"Elixir ist eine dynamische funktionale Sprache entworfen für skalierbare und wartbare Anwendungen." — [elixir-lang.org](http:https://elixir-lang.org/)

Elixir benutzt die battle tested Erlang VM (BEAM) um verteilte und fehlertolerante Systeme mit wenig Latenz out of the box zu ermöglichen.

__Features__:

+ Skalierbar
+ Fehlertolerant
+ Funktionale Programmierung
+ Erweiterbar
172 changes: 172 additions & 0 deletions de/lessons/advanced/concurrency.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
---
layout: page
title: Nebenläufigkeit
category: advanced
order: 4
lang: de
---

Einer der wichtigsten Gründe für den Einsatz von Elixir ist die eingebaute Unterstützung von Nebenläufigkeit. Dank der Erlang VM (BEAM) ist Nebenläufigkeit in Elixir einfacher als erwartet. Die Nebenläufigkeit basiert auf dem Actor Model, bei dem ein abgeschlossener Prozess mit anderen Prozessen durch message passing kommuniziert.

In dieser Lektion werden wir uns die Nebenläufigkeitsmodule anschauen, welche mit Elixir geliefert werden. Im darauf folgenden Kapitel werden wir OTP behandeln, die diese Module implementieren.

{% include toc.html %}

## Prozesse

Prozesse in der Erlang VM sind leichtgewichtig und laufen verteilt auf allen CPUs. Während sie wie native Threads wirken sind sie simpler und es ist nicht ungewöhnlich mehrere Tausend nebenläufige Prozesse in einer Elixiranwendung zu haben.

Der einfachste Weg einen Prozess zu erzeugen ist durch `spawn`, welche eine anonyme oder benannte Funktion entgegen nimmt. Wenn wir einen neuen Prozess erzeugen gibt uns dieser einen _Process Identifier_, auch PID genannt, zurück, welcher den Prozess in unserer Anwendung eindeutig identifiziert.

Für den Start schreiben wir ein Modul und definieren eine Funktion, die wir gerne laufen lassen würden:

```elixir
defmodule Example do
def add(a, b) do
IO.puts(a + b)
end
end

iex> Example.add(2, 3)
5
:ok
```

Um die Funktion asynchron auszuwerten benutzen wir `spawn/3`:

```elixir
iex> spawn(Example, :add, [2, 3])
5
#PID<0.80.0>
```

### Message Passing

Zur Kommunikation benutzen Prozesse message passing. Zwei Komponenten werden hierfür benötigt: `send/2` und `receive`. Die Funktion `send/2` erlaubt uns Nachrichten an PIDs zu schicken. Auf der anderen Seite nutzen wir `receive` um Nachrichten zu empfangen. Falls keine Übereinstimmung gefunden wird läuft die Ausführung ohne Unterbrechung weiter.

```elixir
defmodule Example do
def listen do
receive do
{:ok, "hello"} -> IO.puts "World"
end

listen
end
end

iex> pid = spawn(Example, :listen, [])
#PID<0.108.0>

iex> send pid, {:ok, "hello"}
World
{:ok, "hello"}

iex> send pid, :ok
:ok
```

Bei genauer Betrachtung des Codes fällt auf, dass die `listen/0` Funktion rekursiv ist, was unserem Prozess erlaubt mehrere Nachrichten zu empfangen. Ohne Rekursion würde unser Prozess einfach beendet werden, nachdem die erste Nachricht ausgewertet wurde.

### Kopplung von Prozessen

Ein Problem mit `spawn` ist mitzubekommen, wenn ein Prozess abgestürzt ist. Dafür müssen wir unsere Prozesse mit `spawn_link` verbinden. Zwei auf diese Art verbundene Prozesse bekommen mit, sollte der andere abstürzen:

```elixir
defmodule Example do
def explode, do: exit(:kaboom)
end

iex> spawn(Example, :explode, [])
#PID<0.66.0>

iex> spawn_link(Example, :explode, [])
** (EXIT from #PID<0.57.0>) :kaboom
```

Manchmal wollen wir nicht, dass ein abgestürzter Prozess den aktuelle Prozess zum abstürzen bringt. Dafür müssen wir die exits abfangen. Beim Abfangen von exits werden sie als Nachrichtentupel empfangen: `{:EXIT, from_pid, reason}`.

```elixir
defmodule Example do
def explode, do: exit(:kaboom)
def run do
Process.flag(:trap_exit, true)
spawn_link(Example, :explode, [])

receive do
{:EXIT, from_pid, reason} -> IO.puts "Exit reason: #{reason}"
end
end
end

iex> Example.run
Exit reason: kaboom
:ok
```

### Monitoring von Prozessen

Was wenn wir zwei Prozesse nicht verbinden wollen, aber dennoch informiert werden? Dafür können wir Prozesse mit `spawn_monitor` überwachen. Wenn wir einen Prozess überwachen bekommen wir eine Nachricht falls der Prozess abstürzt, ohne dass unser aktueller Prozess mitabstürzt. Ebensowenig müssen wir dazu exits abfangen.

```elixir
defmodule Example do
def explode, do: exit(:kaboom)
def run do
{pid, ref} = spawn_monitor(Example, :explode, [])

receive do
{:DOWN, ref, :process, from_pid, reason} -> IO.puts "Exit reason: #{reason}"
end
end
end

iex> Example.run
Exit reason: kaboom
:ok
```

## Agenten

Agenten sind eine Abstraktion über Hintergrundprozesse welche einen Zustand beibehalten. Wir können sie von anderen Prozessen innerhalb unserer Anwendung und aller Knoten abrufen. Der Zustand unserer Agenten wird auf den Rückgabewert unserer Funktion gesetzt:

```elixir
iex> {:ok, agent} = Agent.start_link(fn -> [1, 2, 3] end)
{:ok, #PID<0.65.0>}

iex> Agent.update(agent, fn (state) -> state ++ [4, 5] end)
:ok

iex> Agent.get(agent, &(&1))
[1, 2, 3, 4, 5]
```

Durch Benennung eines Agenten können wir diesen direkt ansprechen, anstatt auf dessen PID zurückgreifen zu müssen:

```elixir
iex> Agent.start_link(fn -> [1, 2, 3] end, name: Numbers)
{:ok, #PID<0.74.0>}

iex> Agent.get(Numbers, &(&1))
[1, 2, 3]
```

## Tasks

Tasks erlauben eine Funktion im Hintergrund auszuführen und deren Rückgabewert später zu erhalten. Sie sind besonders nützlich wenn aufwendige Berechnungen durchgeführt werden, ohne die Ausführung der Anwendung zu blockieren.

```elixir
defmodule Example do
def double(x) do
:timer.sleep(2000)
x * 2
end
end

iex> task = Task.async(Example, :double, [2000])
%Task{pid: #PID<0.111.0>, ref: #Reference<0.0.8.200>}

# Führe langwierige Berechnung durch

iex> Task.await(task)
4000
```
89 changes: 89 additions & 0 deletions de/lessons/advanced/escripts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
---
layout: page
title: Ausführbare Dateien
category: advanced
order: 3
lang: de
---

Um ausführbare Dateien in Elixir zu erstellen werden wir escript benutzen. Escript erzeugt eine ausführbare Datei, welche auf jedem System lauffähig ist, auf dem Erlang installiert ist.

{% include toc.html %}

## Einstieg

Um eine ausführbare Datei mit escript zu erzeugen gibt es nur wenige Dinge zu tun: Eine `main/1` Methode erzeugen und das Mixfile anpassen.

Wir starten mit der Erzeugung eines Moduls, welches als Einstiegspunkt für unsere ausführbare Datei dienen soll. Dort werden wir `main/1` implementieren:

```elixir
defmodule ExampleApp.CLI do
def main(args \\ []) do
# Mache irgendetwas
end
end
```

Als nächstes müssen wir für unser Projekt in unserem Mixfile die `:escript` Option aufnehmen. Dazu müssen wir noch ein `:main_module` festlegen:

```elixir
defmodule ExampleApp.Mixfile do
def project do
[app: :example_app,
version: "0.0.1",
escript: escript]
end

def escript do
[main_module: ExampleApp.CLI]
end
end
```

## Argumente parsen

Mit unserer erstellten Anwendung können wir dazu übergehen Kommandozeilenargumente zu parsen. Um das zu tun werden wir Elixirs `OptionParser.parse/2` mit der `:switches` Option nutzen, um darauf hinzuweisen, dass unser flag boolean ist:

```elixir
defmodule ExampleApp.CLI do
def main(args \\ []) do
args
|> parse_args
|> response
|> IO.puts
end

defp parse_args(args) do
{opts, word, _} =
args
|> OptionParser.parse(switches: [upcase: :boolean])

{opts, List.to_string(word)}
end

defp response({opts, word}) do
if opts[:upcase], do: word = String.upcase(word)
word
end
end
```

## Erstellen

Sobald wir die Konfiguration unserer Anwendung mit escript abgeschlossen haben ist die Erzeugung einer ausführbaren Datei mit der Hilfe von Mix einfach:

```elixir
$ mix escript.build
```

Let's take it for a spin:

```elixir
$ ./example_app --upcase Hello
HELLO

$ ./example_app Hi
Hi
```

Das wars. Wir haben unsere erste ausführbare Datei in Elixir mit escript erzeugt.
Loading

0 comments on commit 99f23a2

Please sign in to comment.