 else response to that joke, because in retrospect, it's kind of a joke in poor taste. But I keep trying it anyway. Yeah, so my name's Celine. I'm a software engineer at a company called Braintree in Chicago. I'm putting my information up here now in case you, like, want to write it down, have any questions. Feel free to reach out. I love making new friends. Also, I love feedback. So if you have any feedback for me, these are really great forums to give them to. I'm going to post this again at the end of the talk. So this is great. This is kind of a talk about computer science. How many people, I imagine maybe there are at least a few people in the audience who have at least heard of structured interpretation of computer programs, the scheme. Cool. Has anyone in the audience watched the video lectures that are posted on the MIT open source version of it? It was a crap shoot. I watched half of the first one and then haven't really picked it back up again. I think hopefully some of you guys can relate to that experience. But it did really strike me. There's a gentleman named Hal Abelson, I think, is the person who gives that lecture. It looks like it's from the 80s. It's really fantastic. And I love a lot of the things that he says in it. He says, welcome to this class on computer science, except that that's not really a good name for it because it's not really science and it's not really about computers. So, you know, there are reasons that we call it that. He then likens it to the study of geometry, which was developed initially by the ancient Egyptians. The name for it comes from Gaia, which means earth and Metron, which means to measure. It was developed as a way of like surveying land. So much like the ancient Egyptians developed these sort of rudimentary like fundamentals of geometry. Geometry then developed into a way of talking precisely about declarative knowledge, a way of talking about what is true. Mr. Abelson says that he believes that centuries from now, people will look back at those 20th century primitives and think like, oh, yeah, those folks were fiddling around with these gadgets called computers, but really they were developing a formalized process, a formalized way to talk about intuitions, about process. And I really like that. I've heard it said elsewhere that computer science is a study of process. And I think that if that's true, then programming is the application of that study, or at least one application of that study. As I mentioned, I have a degree in music, and as such, I've been noticing a lot of musicians in the field since I transitioned into tech. How many people in the audience today dabble in music or know a little bit about it? Cool. Is there anyone in the audience who feels like they really don't know anything about music? Awesome. I'm so glad that there are both people who identify with both sides here. I'm hoping that this talk will be very clear to all of us in the room, because it approaches things from the code side. Another idea I want to call out before we get started proper is I went to Strange Loop this year, and there was a talk given by a gentleman named Chris Ford. He talked about ethnomusicology, African polyrhythms, and polyphony, and I really, really enjoyed a lot of the way that he talked about these ideas. He talked specifically about some aspects that music have in common to programming, and that is that they both use an abstract form of representation to communicate ideas. They both use this abstract form of representation to communicate ideas about a process. Then there's also a lot of composition and analysis in both pieces. I think this is probably true of many other fields as well, but perhaps obviously the reason I noticed it in music is because I studied music for most of my life. What we're going to do today in this talk is we're going to look at one piece of music. It was written by a gentleman named Steve Reich, published in 1973. It's part of an era of academic music called minimalism. You can maybe see just from looking at this page why it's called minimalism, especially if you do have any kind of background or experience with music. A lot of classical music pieces take up an entire book, and this one is half a page. It is just in appearance, very minimalistic. We're going to deconstruct the representation on this page, some of the more traditional musical representation that we see here. We're going to deconstruct the process and figure out how to describe it conceptually, and then we're going to recompose that process using a tool that's familiar to all of us, Ruby and we're going to use Sonic Pi to help with that process, but I'm not going to focus too much on that tool. We can talk about it after if you all want to. Great. I'm really excited. Let's get going. In beginning to break down this piece, the first thing I want to point out is that there are five of what we call stanzas. Each stanza is this like broader line. We read music just in case anyone doesn't know. We read music from left to right, top to bottom. Each of the stanzas is made up of two parts. You can see them delineated in the top left hand corner with the words clap one and clap two. This indicates that there are two performers in the piece, and the instrument is clapping, which is not terribly common in the world of academic music, just to point that out. Each stanza has two lines, which represent two parts. There are five stanzas. The next thing I want to point out is a structure that formal music calls a bar or a measure. In each of these broader stanzas, there are three bars or measures, and appropriately enough, those are delineated by these vertical bars in between each group of notes. Right? Cool. One, two, three. We got that. Next, I want to bring your attention to the top of the page, where we see a little piece of instructions here. The first bit of this that's got a note and it says equals 160, 184. That's just a tempo marking. We're not going to worry too much about that for the purposes of this talk. After that, though, it says repeat each bar 12 times. That's instructions from the composer. If you look down at each of these bars or measures in the score, you can see little colons on each line. Traditionally in music, when you read a few bars of music and you come to the colon, that means repeat from where you see the first colon that's facing to the right. In this case, Steve Reich has given us very specific instructions. He's saying, don't repeat the way you normally would just once. Repeat it 12 times. That's how this is meant to be read. A disclaimer here, we're not going to repeat it 12 times. We're going to repeat it four times because this is my talk and I think 12 is too many for this talk. Fantastic. One last thing I want to point out before we move on is that the top part has exactly the same pattern of notes in every measure. It plays the same thing the whole time. That is arguably the boring part of the piece, but it's also a really important part of the piece. It gives the changing part something to work against. Let's take a closer look at that first measure where both parts are the same. Let's break down some of the representation we see in here. Despite the way this looks, it looks like these are lots of different notes, but don't be fooled. This musical notation is a little bit weird. I always thought it was crazy how inconsistent the way that notes visually are represented, but these are all these notes represent exactly the same rhythmic value. In fact, the little markings between the notes, those are called rests. They kind of look like flags. Those also represent the same rhythmic value, which is kind of cool because it's the only, looking back at the whole score, those are the only notes in rest in the entire piece. That coupled with the fact that it's a rhythmic piece makes this piece really easy to represent in code because we don't have to worry about pitch at all and we don't have to worry about different rhythmic values even. We just have to worry about the order in which the rhythmic values appear. That's kind of neat. I do want to play this rhythmic pattern to you because it's really the theme of the piece. You hear it a lot, a lot, a lot. It goes like this. I'm going to do that again and emphasize the rests with my hands. I like thinking of rests and music as white space coming at it from a code perspective. Cool. I also have a mnemonic for that because I found that especially in teaching music, lyrics make it a lot easier to remember rhythms and melodies and stuff. I've got a fun story behind this. I was a big fat choir nerd when I was in college. My college choir used to go on tour every winter break and being music nerds. We sat on the back of the bus one year and tried to learn how to play this piece of clapping music because all it takes is a couple of people, hands, and familiarity with the process of the piece. We'd sit in the back of the bus and play clapping music and we came up with these lyrics that I'm about to share with you. With good reason, I think anyone who has ever been on a tour bus for more than a couple of days understands the sentiment that these lyrics express. They go like this. There is no pooping on the bus. So now you have a really easy way to remember this thematic rhythm. We'll get back to that. The really fun thing about this really simple representation is that there is perhaps an obvious way, definitely a very simplistic way to represent this in code and particularly in Ruby code and that's with arrays. I've chosen to represent here the first part with one array on top and the second part with another array on bottom. And appropriately enough, I've chosen to represent the spaces where there is a note or a clock with a 1 and the spaces where there isn't with a 0. Gotta love parallelism. Cool. So let's now take a look at the rest of the score. First measure. I've already pointed it out but you may have noticed as well that the second part changes throughout the piece. And spoiler alert, it's a recursive pattern. So before we move on breaking down notes and process, let's be really aggressive about defining our terms and make sure that we talk from a broad perspective about what recursion is. Is there a brave soul in the audience who might want to volunteer their own definition of recursion? Go for it. Self-reference. That's a good way of putting it. There are so many different definitions. This is the first one I found. I'm doing that Wikipedia thing. And this particular definition is, I think, more particular. It's more honed into computers than what you offered up. And that's really common. We're all familiar with the computer-based reference or definition of recursion. So I went and found another one which tries to be really particular to mathematics. But I really like the part of this that says recursion is generated by repeating a particular operation. And I think of examples of recursion that occur outside of mathematics or computers, like when two mirrors are facing each other, that's arguably recursion. And what is the repeated operation here? It's reflecting. They're reflecting each other across. I mean, there's no kick in mirror reflecting, but that doesn't matter. I like this definition specifically because it's not particular to computers. And what we're trying to do here is build a bridge across two different fields by analyzing similar processes. So thinking of it as a repeated operation serves our purpose really well for that. Cool. So looking again at the rest of the score, the second part, we know it's a recursive process. Let's see if we can pinpoint that repeated operation. And let's do that by taking a closer look at the second measure. This measure, we've established that the first part is the same. So we have an idea of what, because it's only the second measure, we have an idea of what the part was in the measure right before it, and we can look at the second part and figure out exactly what happens. Again, do I have a brave soul in the audience who might want to volunteer if they've noticed what this repeated operation is? Yeah. The whole pattern has been shifted back, and the first note has been placed at the end of the bar. Very well said, sir. Thank you. Cool. And that just keeps going until the end of the piece. But I'll take another look at that later. I keep getting ahead of myself. We can represent these notes and rhythms and patterns in code again fairly easily. Same thing. Ones represent clops, zeros represent a rest. And as a side note, I really like the way it looks when they are different, because you can see where the beats line up with each other and where they're doubled. It's great. Cool. So taking a look at the rest of the piece, it's easy to visualize the way that that operation is repeated throughout the piece. And you can sort of trace the lines through the piece if you'd like to and land at the very last measure in the fifth stanza where they return to playing the same pattern again. Cool. So now we get to get into the part where we sort of figure out how to recompose this process. I think we've got a solid understanding of what the process is overall. How do we recompose this with code? What needs representation? There are the two parts, the two performers that will need some kind of representation. There's what they're playing, the notes on the page. We've already started with that a little bit. And then there's also how to play the parts, that process. How do we represent that in code? We have a conceptual understanding of it. How do we represent that with the tools that we're already familiar with? So I've taken the liberty of establishing a couple pieces of this already. There's the two parts. I will take just a small minute to say Sonic Pi is a DSL over Ruby and there are a couple of weird quirks to it in that regard. And so I have not defined any of this within a class like perhaps you normally would in object-oriented Ruby, but I'm still using instance variables so there. So I've assigned two different packaged voices to instance variables. We've got a high-pitched, percussive voice and a mid-pitched, percussive voice. And this is just to provide us a little bit of texture and variety because in part because it's a computer, they're coming from the same speakers if it was the same pitch, it would be a little bit harder to differentiate between parts. Honestly, I don't think this helps too much, but it does help a little bit. And then we've already established that we have the baseline part. I was supposed to deliver that differently so that I could focus on the pun a little bit more. Apologies. Yeah, I've called our part that stays the same, the baseline. And then we have what is absolutely named a rotating part. I thought I deleted the clone. I figured out that wasn't absolutely necessary. But fortunately for us, Ruby has a packaged method in it that will do exactly the operation we needed to do. It's called rotate. It's beautiful. Lastly, the interesting part. Not that the rest of this hasn't been interesting, but I really like recursion and it's fun to play with. And we get to do that now. So let's redefine some of these important terms for anyone who might be watching this who is not familiar with music. I think this is an important thing to do. We've got our measures or bars, which is a grouping of notes. We've got a section. I haven't said this word before. I'm calling the repetition of measures a section. Remember in the score when he said repeat each measure 12 times? That's what I'm calling a section. We're repeating it four times as a reminder. I just couldn't really think of a better way of describing that. So a section, a repeated section. And then I've defined a couple of methods for us to start with. Play note and play rest. They're fairly straightforward just because every note and every rest is the same rhythmic value and it's not really that interesting or important to the process. So you're welcome. Other helper methods I think would be a good way to move forward. I'm proposing that the design of this particular composition, we tell the computer how to play a measure, how to play a section, and then how to play both parts playing a section at the same time. Normally if two humans were clapping this piece it would be two separate brains performing one process together. A computer arguably can be two separate brains. There's not really a basis of comparison there or there is but I don't want to get into it. And we have to tell the computer how to play two parts at the same time. So for playing the measure we take two arguments, the pattern of notes that we want to play and the voice that we want to play them. So for each value in this pattern if it's a one we play the note with the voice given and if it's a zero we play the rest. And that I can tell you what that sounds like. At least I think I can. That makes sense. We already learned that rhythm. So then to play the section, there are so many different ways to implement this. I did it this way for reasons. I think probably if it were in a class you would want to extract the number into a constant or something like that. But this is how it turned out and the code works. It still sounds like things and I think that's really fun. It sounds like this. Makes sense so far? Great. And then lastly we know how to tell the computer to play both parts at the same time. We'll do that a section at a time because that kind of makes sense to the structure of this process. And in Sonic Pi the way that's done is that we just wrap one play section call in a thread and then let the other play. That's the way it works. But it also makes sense. You can just tell it to have a separate process and go. So that sounds, I'll do what I tell you. That sounds like this. Cool. And just for a little context I'll shout back to the thing I was saying earlier. This is one part. Is that one part? Yeah. And this is two parts. So maybe you can hear the difference. To me it just sounds a little bit louder. It comes more obvious when they're playing different things. Back to the slide. Now it's time for the recursion. Thank you. I'm obviously very excited about this part. Let's continue to be thorough about defining our terms and just go over the pieces of recursion. We've already been so good about defining terms anyway. So let's do that right now. Recursion, in my case, is typically broken down into three or so parts. There's the part where the function is called within itself. There is the kick, often also called the base case. You might be familiar with either of those names that tells the function to exit after a certain point of repeating the operation. And then there's the part of it that changes something so that it can get to the kick. And often that's, you can think of it in a couple of different ways. There is the repeated operation itself, the part that the function is meant to call. The classic example is in the factorial problem. The thing that the function does is multiply two numbers and the thing that the function changes is that one of the numbers is subtracted by one every time it repeats. If that makes sense. Cool. So we're going to start with the obvious part written for us with this very aptly named method, play recursive bit. We pass in a part that we want it to play recursively. And then we call the method within itself. And we'll get to what we pass into the repeated call in a minute. I just gave it away. So then we have the base case, which is Did anyone notice this earlier? Any volunteers to interpret the code I have on screen? Go for it. Right, exactly. The very last measure they line up again. So we know we're done with the recursive process when the two parts line up again and are playing the same thing. And incidentally Steve Reich called this piece and a lot of other similar pieces that he wrote phase music for exactly that reason. Because it's like it's phasic. You start with one thing and you kind of rotate through a phase and then it stops. It's really neat. Right, so next, what's the change that we want to pass into the recursive call? Go for it. Exactly. Rotating part.rotate. And that'll you guys know. That signals our thing that it needs to change and it'll keep going until the base case. We just need one more piece which is the actual action that we want to happen. Any takers? Yeah, play the section. Sweet. So we've told both parts to play the section. We are returning when the piece is done but when it's not done we're just going to keep playing it with the part rotated. So let's put all these pieces together. We could potentially just use the method we just wrote, play recursive bit and pass in a rotated baseline. But there's one problem with that. Any takers? Does anyone already know? I see a hand halfway raised in back. Yeah. Right, exactly. Yeah. The problem with doing it this way is that as the gentleman in back said, the first section you wanted to play is going to be the same. It won't immediately exit because we're passing in the rotated baseline. It just won't actually play the whole piece. So we'll want to play the section the same way first and then go through the recursive bit into the kick. You could arrange the actual recursive method a little bit differently so that the kick is at the top and it just doesn't play again when they're the same. But then you would have to put both parts play section at bottom and it doesn't really matter. It's the same thing. Fantastic. So we're going to listen to this all at the same time. The way the pieces arranged it ends up just feeling really good at the end of it. So I want to go through some thank yous and post some links before we start listening to it. So I've got a link to Sonic Pi because it's a really neat little DSL. If anyone wants to explore that, do it. I've got the completed code up on my GitHub as well as a PDF of my slides. I'm using dexset. There's a mark down up there too if anyone's interested. The name of the composer in the piece up there, again, if anyone's interested. And I do want to thank a couple of my co-workers who helped me prepare and mentored me through this process, John Downey and Josh Larson. I want to thank Dev Bootcamp for initially asking me to give a talk about music and programming and inspiring this. And then of course Sam Aaron and anyone who's ever contributed to Sonic Pi I like it a lot. Cool. So let's do... So in doing this I'm going to pull Sonic Pi over here to the viewer. I'm going to make this a little smaller, I hope. There we go. I've written in a logging method. It'll tell us when the base case is achieved and also just write out each part the first time it's played so that we can see that visual of each note against each other and how the rotation is occurring. That's a very good question. You mean like out of different speakers? Thank you. The question is can we play the baseline out of one speaker and the rotating part out of another speaker so it's a little bit easier to hear the difference. I would like to figure out what the best way is to do that as it was we had a little bit of trouble with the line out on the computer and the sounds that you heard were provided to you by a microphone sitting next to the speaker. So that is very good feedback. I'll keep that in mind for if I give this talk another time and try to make that improvement. Thank you. Oh, that's a great question. What is the editor that I'm using to write the code in there? Yeah. I was built into Sonic Pi. Sonic Pi was originally developed for use on Raspberry Pi, but they developed an OSX port for it. I'm honestly not a huge fan of the editor in Sonic Pi, especially after having learned and gotten used to Vim. I used to use Sublime even all the keyboard shortcuts in Sublime. Maybe there are keyboard shortcuts in Sonic Pi and I just didn't take the time to learn them, but I became mildly frustrated when I was developing this, having to copy and paste with a mouse and click on things. That said, though, I didn't have to write my own system of turning code into sound, which was really nice. Cool. Thanks again so much for coming.