# Ringe mit verketteten Kommandos

Zusätzlich zu den Konstruktoren wie `range` und `spread` können neue Ringe auch erzeugt werden, indem schon existierende manipuliert werden.

## Verkettete Kommandos

Nimm’ einen einfachen Ring, um das auszuprobieren:

    (ring 10, 20, 30, 40, 50)

Was, wenn wir die Reihenfolge umkehren wollen? Dann verwenden wir das verkettete Kommando `.reverse`, um den Ring umzudrehen:

    (ring 10, 20, 30, 40, 50).reverse  #=> (ring 50, 40, 30, 20, 10)

Was nun, wenn wir die ersten 3 Werte aus dem Ring haben möchten?

    (ring 10, 20, 30, 40, 50).take(3)  #=> (ring 10, 20, 30)

Und was, wenn wir schließlich den Ring mischen wollten?

    (ring 10, 20, 30, 40, 50).shuffle  #=> (ring 40, 30, 10, 50, 20)

## Mehrteilige Ketten

So haben wir schon viele Möglichkeiten neue Ringe zu erzeugen. Noch besser wird es, wenn Du diese Kommandos miteinander verkettest.

Wie wäre es z. B. wenn Du den Ring mischst, das erste Element weglässt, und dann die nächsten 3 Elemente nimmst?

Gehen wir das Schritt für Schritt durch:

1. `(ring 10, 20, 30, 40, 50)` - Dein Ring am Anfang
2. `(ring 10, 20, 30, 40, 50).shuffle` - mischt - `(ring 40, 30, 10, 50, 20)`
3. `(ring 10, 20, 30, 40, 50).shuffle.drop(1)` - das erste Element weglassen - `(ring 30, 10, 50, 20)`
4. `(ring 10, 20, 30, 40, 50).shuffle.drop(1).take(3)` - 3 Elemente nehmen - `(ring 30, 10, 50)`

Siehst Du, wie wir eine lange Kette dieser Methoden einfach dadurch erzeugen können, dass wir sie aneinander hängen? Wir können das in jeder beliebigen Reihenfolge tun; damit haben wir viele unterschiedliche Möglichkeiten, neue Ringe aus schon bestehenden zu erzeugen.

## Unveränderlichkeit

Diese Ringe haben eine leistungsstarke und wichtige Eigenschaft. Sie sind unveränderlich (engl. immutable). Das heisst, dass die Verkettung von Methoden, von der wir hier sprechen, die Ringe nicht verändert sondern neue Ringe erzeugt. Du kannst also Ringe in verschiedenen Threads verwenden und sie mit verketteten Kommandos verändern, ohne dass derselbe Ring in einem anderen Thread verändert wird.

## Methoden, die verkettet werden können

Hier kommt eine Liste der Methoden, die miteinander verkettet werden können:

- `.reverse` - gibt eine umgedrehte Version des Rings zurück
- `.sort` - stellt eine sortierte Version des Rings her
- `.shuffle` - liefert eine neu gemischte Version des Rings
- `.pick(3)` - liefert einen Ring nachdem 3-mal `.choose` angewendet wurde
- `.pick(3)` - liefert einen Ring nachdem 3-mal `.choose` angewendet wurde
- `.take(5)` - liefert einen neuen Ring, der nur die ersten 5 Elementen enthält
- `.drop(3)` - liefert einen neuen Ring, der alles außer den ersten 3 Elementen enthält
- `.butlast` - liefert einen neuen Ring ohne das letzte Element
- `.drop_last(3)` - liefert einen neuen Ring ohne die letzten 3 Elemente
- `.take_last(6)`- liefert einen neuen Ring, der nur die letzten 6 Elemente enthält
- `.stretch(2)` - wiederholt jedes Element im Ring zweimal
- `.repeat(3)` - wiederholt den ganzen Ring 3-mal
- `.mirror` - hängt eine umgekehrte Version des Rings an die ursprüngliche an
- `.reflect` - wie `.mirror`, verdoppelt aber nicht die mittleren Werte
- `.scale(2)` - gibt einen neuen Ring zurück, der alle Elemente des ursprünglichen Rings mit 2 multipliziert enthält (Voraussetzung: Ring enthält nur Zahlen)

Die Verkettungsfunktionen mit Zahlenparametern können natürlich auch mit anderen Werten aufgerufen werden. Anstelle von `.drop(3)` kann man zum Beispiel `.drop(5)` aufrufen, um die ersten fünf Elemente wegfallen zulassen.