# Ringe

Eine interessante Spielart von normalen Listen sind Ringe. Wenn Du ein bisschen Programmiererfahrung hast, könntest Du Ringspeicher (engl. „Ring Buffer“) oder Ring-Arrays kennen. Wir nennen die hier nur Ring – das ist kurz und einfach.

Im vorherigen Abschnitt über Listen haben wir gesehen, dass wir Elemente aus einer Liste über den Index holen können:

    puts [52, 55, 59][1]

Was passiert jetzt wohl, wenn Du den Index `100` abfragen willst? Offensichtlich gibt es kein Element mit dem Index 100, da die Liste nur drei Elemente enthält. Also gibt Sonic Pi `nil` zurück, was “nichts” bedeutet.

Stell Dir vor, einen Zähler wie den aktuellen Takt zu haben, der kontinuierlich wächst. Lass uns so einen Zähler und unsere Liste anlegen:

    counter = 0
    notes = [52, 55, 59]

Jetzt können wir mit unserem Zähler auf eine Note in unserer Liste zugreifen:

    puts notes[counter]

Super, da kam `52` heraus. Jetzt erhöhen wir den Zähler (`inc`, die Abkürzung für englisch “to increment” = erhöhen) und bekommen damit eine neue Note:

    counter = (inc counter)
    puts notes[counter]

Ok, jetzt kommen `55` und beim nächsten Mal `59` heraus. Wenn wir das jedoch jetzt noch einmal machen, werden wir aber nicht mehr genug Zahlen in unserer Liste haben und werden stattdessen `nil` zurück bekommen. Was wäre, wenn wir dann einfach wieder vom Anfang der Liste anfangen wollten? Genau dafür gibt es Ringe.

## Ringe erzeugen

Es gibt zwei Möglichkeiten, Ringe zu erzeugen. Die erste ist, die `ring` Funktion mit den gewünschten Elementen des Rings als Parameter zu verwenden:

    (ring 52, 55, 59)

Die zweite Möglichkeit ist es, eine normale Liste mit der Nachricht `.ring` zu einem Ring umzuwandeln:

    [52, 55, 59].ring

## Auf Ringelemente zugreifen

Sobald wir einen Ring haben, können wir ihn auf die gleiche Art wie eine Liste verwenden. Die einzige Ausnahme ist, dass Du Indizes verwenden kannst, die negativ oder größer als der Ringinhalt sind. Diese fangen dann wieder am Anfang an, um immer auf ein Element des Rings zu zeigen:

    (ring 52, 55, 59)[0] #=> 52
    (ring 52, 55, 59)[1] #=> 55
    (ring 52, 55, 59)[2] #=> 59
    (ring 52, 55, 59)[3] #=> 52
    (ring 52, 55, 59)[-1] #=> 59

## Ringe verwenden

Angenommen, wir bilden die Nummer des aktuellen Takts in einer Variable ab. Diese Nummer können wir als Zugriffsindex für unseren Ring verwenden, um abzuspielende Note, Release-Zeiten oder andere sinnvolle Dinge, die wir in unserem Ring abgelegt haben, abzurufen.

## Skalen und Akkorde sind Ringe

Gut zu wissen: Die Listen, die von `scale` und `chord` zurückgegeben werden, sind Ringe. Du kannst also mit beliebigen Indizes auf sie zuzugreifen.

## Ring-Konstruktoren

Zusätzlich zu `ring` gibt es noch eine Anzahl weiterer Funktionen, die Ringe für uns erzeugen.

- `range` lädt ein, einen Startpunkt, einen Endpunkt und eine Schrittgröße zu definieren.
- `bools` erlaubt Dir `1`er und `0`er als prägnante Darstellung boolscher Werte zu nutzen.
- `knit` erlaubt Dir, eine Abfolge wiederholter Werte zu “stricken” (engl. “to knit”).
- `spread` verteilt boolschen Werte mit dem Euklidischen Algorithmus in einem Ring.

Mehr Informationen zu diesen Funktionen findest Du in der entsprechenden Dokumentation.