# Ring-Ketten

Neben der Verwendung von Konstruktoren wie `range` und `spread` können wir neue Ringe auch dadurch erzeugen, das wir bereits existierende Ringe verändern.

## Befehle verketten

Um dies auszuprobieren, verwende einen einfachen Ring:

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

Was, wenn wir diese Reihe umkehren wollen? Nun, wir verwenden den Verkettungsbefehl `.reverse`, um den Ring umzudrehen:

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

Ok, und wenn wir nur die ersten 3 Werte aus dem Ring haben wollten?

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

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

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

## Mehrfache Ketten

Auf diese Art haben wir bereits mächtige Möglichkeiten neue Ringe zu erzeugen. Noch mächtiger werden sie allerdings, wenn du mehrere dieser Befehle verkettest.

Wie wäre es den Ring zu mischen, das erste Element wegzulassen, und dann die 3 folgenden Elemente zu verwenden?

Lass uns das Schritt für Schritt durchgehen:

1. `(ring 10, 20, 30, 40, 50)` - dein anfänglicher Ring
2. `(ring 10, 20, 30, 40, 50).shuffle` - mischt ihn zu - `(ring 40, 30, 10, 50, 20)`
3. `(ring 10, 20, 30, 40, 50).shuffle.drop(1)` - mischt und lässt dann das erste Element weg - `(ring 30, 10, 50, 20)`
4. `(ring 10, 20, 30, 40, 50).shuffle.drop(1).take(3)` - mischt, lässt das erste Element weg und nimmt 3 - `(ring 30, 10, 50)`

Kannst du sehen, wie wir eine lange Kette dieser Methoden einfach dadurch erzeugen können, dass wir sie aneinander kleben? Wir können das in jeder beliebigen Reihenfolge tun, und damit haben wir einen extrem mächtigen Weg, um neue Ringe aus bereits bestehenden zu erzeugen.

## Unveränderlichkeit

Diese Ringe haben eine mächtige und wichtige Eigenschaft. Sie sind unveränderlich (immutable) - sie können nicht verändert werden. Das bedeutet, dass die Verkettungsmethoden, von denen wir in diesem Abschnitt sprechen, die Ringe nicht verändern sondern eher neue Ringe erzeugen. Das bedeutet, du kannst Ringe über verschiedene Threads hinweg teilen und anfangen sie innerhalb eines Threads zu verketten, ohne dabei irgend einen anderen Thread zu verändern, der auf den gleichen Ring zugreift.

## Verfügbare Verkettungsmethoden

Dies ist eine Liste der Verkettungsmethoden, mit denen du spielen kannst:

- `.reverse` - gibt eine umgedrehte Version des Ringes zurück
- `.sort` - erzeugt eine sortierte Version des Ringes
- `.shuffle` - erzeugt eine gemischte Version des Ringes
- `.pick` - liefert einen Ring mit den Resultaten wie 1 mal `.choose`
- `.pick(3)` - liefert einen Ring mit den selben Resultaten wie 3 mal `.choose`
- `.take(5)` - liefert einen Ring, der nur die ersten 5 Elemente enthält
- `.drop(3)` - liefert einen Ring, der alles außer den ersten 3 Elementen enthält
- `.butlast` - liefert einen Ring ohne das letzte Element
- `.drop_last(3)` - liefert einen Ring ohne die letzten 3 Elemente
- `.take_last(6)`- liefert einen Ring, der nur die letzten 6 Elemente enthält
- `.stretch(2)` - wiederholt jedes Element im Ring zweimal
- `.repeat(3)` - wiederholt den Ring als Ganzes 3 mal
- `.mirror` - hängt eine umgekehrte Version des Rings an den Ring an
- `.reflect` - wie `.mirror`, verdoppelt aber nicht den mittleren Wert
- `.scale(2)` - liefert einen neuen Ring mit allen Elementen multipliziert mit 2 (setzt voraus, dass der Ring nur Zahlen enthält)

Natürlich können solche Verkettungsmethoden, die Zahlenparameter annehmen auch andere Werte annehmen. So kannst du anstelle von `.drop(3)` z. B. auch `.drop(5)` aufrufen, wenn du die ersten fünf Elemente wegfallen lassen willst.