Skip to content

Commit 1e8299d

Browse files
committed
Add new tutorial section on rings and beef up lists
1 parent 29eaa8d commit 1e8299d

File tree

2 files changed

+147
-1
lines changed

2 files changed

+147
-1
lines changed

etc/doc/tutorial/08.1-Lists.md

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ play 59
2020

2121
Let's look at other ways to represent this code.
2222

23-
## Chords
23+
## Playing a List
2424

2525
One option is to place all the notes in a list: `[52, 55, 59]`. Our
2626
friendly `play` function is smart enough to know how to play a list of
@@ -46,3 +46,51 @@ play [:E3, :G3, :B3]
4646

4747
Now those of you lucky enough to have studied some music theory might
4848
recognise that chord as *E Minor* played in the 3rd octave.
49+
50+
## Accessing a List
51+
52+
Another very useful feature of a list is the ability to get information
53+
out of it. This may sound a bit strange, but it's no more complicated
54+
than someone asking you to turn a book to page 23. With a list, you'd
55+
say, what's the element at index 23? The only strange thing is that in
56+
programming indexes usually start at 0 not 1.
57+
58+
With list indexes we don't count 1, 2, 3... Instead we count 0, 1, 2...
59+
60+
Let's look at this in a little more detail. Take a look at this list:
61+
62+
```
63+
[52, 55, 59]
64+
```
65+
66+
There's nothing especially scary about this. Now, what's the second
67+
element in that list? Yes, of course, it's `55`. That was easy. Let's
68+
see if we can get the computer to answer it for us too:
69+
70+
```
71+
puts [52, 55, 59][1]
72+
```
73+
74+
OK, that looks a bit weird if you've never seen anything like it
75+
before. Trust me though, it's not too hard. There are three parts to the
76+
line above: the word `puts` , our list `52, 55, 59` and our index
77+
`[1]`. Firstly we're saying `puts` because we want Sonic Pi to print the
78+
answer out for us in the log. Next, we're giving it our list, and
79+
finally our index is asking for the second element. We need to surround
80+
our index with square brackets and because counting starts at `0`, the
81+
index for the second element is `1`. Look:
82+
83+
```
84+
# indexes: 0 1 2
85+
[52, 55, 59]
86+
```
87+
88+
Try running the code `puts [52, 55, 59][1]` and you'll see `55` pop up
89+
in the log. Change the index `1` to other indexes, try longer lists and
90+
think about how you might use a list in your next code jam. For example,
91+
what musical structures might be represented as a series of numbers...
92+
93+
94+
95+
96+

etc/doc/tutorial/08.4-Rings.md

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
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

Comments
 (0)