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.
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
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
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.
Gut zu wissen: Die Listen, die von scale
und chord
zurückgegeben werden, sind Ringe. Du kannst also mit beliebigen Indizes auf sie zuzugreifen.
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.