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.

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