|
| 1 | +# Rings |
| 2 | + |
| 3 | +An interesting spin on standard lists are rings. If you know some |
| 4 | +programming, you might have come across ring buffers or ring |
| 5 | +arrays. Here, we'll just go for ring - it's short and simple. |
| 6 | + |
| 7 | +In the previous section on lists we saw how we could fetch elements out |
| 8 | +of them by using the indexing mechanism: |
| 9 | + |
| 10 | +``` |
| 11 | +puts [52, 55, 59][1] |
| 12 | +``` |
| 13 | + |
| 14 | +Now, what happens if you want index `100`? Well, there's clearly no |
| 15 | +element at index 100 as the list has only three elements in it. So Sonic |
| 16 | +Pi will return you `nil` which means nothing. |
| 17 | + |
| 18 | +However, consider you have a counter such as the current beat which |
| 19 | +continually increases. Let's create our counter and our list: |
| 20 | + |
| 21 | +``` |
| 22 | +counter = 0 |
| 23 | +notes = [52, 55, 59] |
| 24 | +``` |
| 25 | + |
| 26 | +We can now use our counter to access a note in our list: |
| 27 | + |
| 28 | +``` |
| 29 | +puts notes[counter] |
| 30 | +``` |
| 31 | + |
| 32 | +Great, we got `52`. Now, let's increment our counter and get another |
| 33 | +note: |
| 34 | + |
| 35 | +``` |
| 36 | +counter = (inc counter) |
| 37 | +puts notes[counter] |
| 38 | +``` |
| 39 | + |
| 40 | +Super, we now get `55` and if we do it again we get `59`. However, if we |
| 41 | +do it again, we'll run out of numbers in our list and get `nil`. What if |
| 42 | +we wanted to just loop back round and start at the beginning of the list |
| 43 | +again? This is what rings are for. |
| 44 | + |
| 45 | +## Creating Rings |
| 46 | + |
| 47 | +We can create rings one of two ways. Either we use the `ring` function |
| 48 | +with the elements of the ring as parameters: |
| 49 | + |
| 50 | +``` |
| 51 | +(ring 52, 55, 59) |
| 52 | +``` |
| 53 | + |
| 54 | +Or we can take a normal list and convert it to a ring by sending it the |
| 55 | +`.ring` message: |
| 56 | + |
| 57 | +``` |
| 58 | +[52, 55, 59].ring |
| 59 | +``` |
| 60 | + |
| 61 | +## Indexing Rings |
| 62 | + |
| 63 | +Once we have a ring, you can use it in exactly the same way you would |
| 64 | +use a normal list with the exception that you can use indexes that are |
| 65 | +negative or larger than the size of the ring and they'll wrap round to |
| 66 | +always point at one of the ring's elements: |
| 67 | + |
| 68 | +``` |
| 69 | +(ring 52, 55, 59)[0] #=> 52 |
| 70 | +(ring 52, 55, 59)[1] #=> 55 |
| 71 | +(ring 52, 55, 59)[2] #=> 59 |
| 72 | +(ring 52, 55, 59)[3] #=> 52 |
| 73 | +(ring 52, 55, 59)[-1] #=> 59 |
| 74 | +``` |
| 75 | + |
| 76 | +## Using Rings |
| 77 | + |
| 78 | +Let's say we're using a variable to represent the current beat |
| 79 | +number. We can use this as an index into our ring to fetch notes to |
| 80 | +play, or release times or anything useful we've stored in our ring |
| 81 | +regardless of the beat number we're currently on. |
| 82 | + |
| 83 | +## Scales and Chords are Rings |
| 84 | + |
| 85 | +A useful thing to know is that the lists returned by `scale` and `chord` |
| 86 | +are also rings and allow you to access them with arbitrary indexes. |
| 87 | + |
| 88 | +## Ring Constructors |
| 89 | + |
| 90 | +In addition to `ring` there are a number of other functions which will |
| 91 | +construct a ring for us. |
| 92 | + |
| 93 | +* `range` invites you specify a starting point, end point and step size. |
| 94 | +* `bools` allows you to use `1`s and `0`s to succinctly represent booleans. |
| 95 | +* `knit` allows you to knit a sequence of repeated values. |
| 96 | + |
| 97 | +Take a look at their respective documentation for more information. |
| 98 | + |
0 commit comments