Eine interessanter Dreh bei einfachen Listen sind Ringe. Wenn du ein bisschen Programmiererfahrung hast, bist du vielleicht schon einmal auf Ring-Buffer (Ringspeicher) oder Ring-Arrays gestoßen. Wir nennen sie hier - kurz und einfach - Ring.
Im vorherigen Abschnitt über Listen haben wir gesehen, wie wir über den Index-Mechanismus Elemente aus einer Liste holen können:
puts [52, 55, 59][1]
Was passiert jetzt wohl, wenn du den Index 100
abfragen willst? Nun, es gibt offensichtlich kein Element mit dem Index 100, da die Liste nur drei Elemente enthält. Also gibt Sonic Pi nil
zurück, das steht für ‘nichts’.
Stell dir jedoch vor, du hast einen Zähler, wie den aktuellen Beat (Schlag), der kontinuierlich wächst. Lass uns damit unseren Zähler und unsere Liste anlegen:
counter = 0
notes = [52, 55, 59]
Wir können jetzt unseren Zähler verwenden, um auf eine Note in unserer Liste zuzugreifen:
puts notes[counter]
Super, da kam 52
heraus. Nun Lass uns den Zähler erhöhen (increment) und auf eine andere Note zugreifen:
counter = (inc counter)
puts notes[counter]
Gut, jetzt kommt 55
und beim folgenden Mal 59
heraus. Wenn wir das jedoch noch einmal machen, werden wir keine Zahlen mehr in unserer Liste haben, und wir bekommen nil
zurück. Was wäre, wenn wir in diesem Fall einfach wieder vom Anfang der Liste an zählen wollten? Genau dafür gibt es Ringe.
Wir können Ringe auf zwei Arten erzeugen. Entweder wir nutzen die ring
-Funktion, mit den gewünschten Elementen aus dem Rings als Parameter:
(ring 52, 55, 59)
Oder wir nehmen eine normale Liste und wandeln sie mit der Nachricht .ring
in einen Ring um:
[52, 55, 59].ring
Sobald du einen Ring hast, kannst du ihn genauso verwenden wie du eine normale Liste verwenden würdest, mit einer Ausnahme: Du kannst darauf auch solche Indizes verwenden, die negativ oder größer als der Ringinhalt sind - diese machen dann eine Schleife wieder zum Anfang, um immer auf ein Element des Rings zu verweisen:
(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
Lass uns annehmen, wir verwenden eine Variable, die stets die aktuelle Schlagzahl abbildet. Wir können diese Variable in unserem Ring als Index verwenden, um so Noten, Release-Zeiten oder andere sinnvolle Dinge abzurufen, unabhängig davon bei welcher Schlagzahl wir uns gerade befinden.
Es ist nützlich zu wissen, das die Listen, die von scale
und chord
zurückgegeben werden, auch Ringe sind und du so mit beliebigen Indizes auf sie zugreifen kannst.
Zusätzlich zu ring
gibt es eine Anzahl weiterer Funktionen, die Ringe für uns erzeugen.
range
lädt dich dazu ein, einen Startpunkt, einen Endpunkt und eine Schrittgröße festzulegen.bools
erlaubt dir 1
en und 0
en als Kurzform für boolesche Werte zu nutzen.knit
erlaubt dir, eine Abfolge zu wiederholender Werte zu stricken (to knit).spread
erzeugt einen Ring boolescher Werte in euklidischer Verteilung.Für weitere Information sieh dir die Dokumentation zur jeweiligen Funktion an.