 Let's do this thing. So welcome to four programming paradigms in 45 minutes. When I proposed this talk, I did not think they would accept it. When I got the acceptance, I'm like, what the heck am I going to do? There are 190 slides in this talk. It's going to be fast. Get ready to hang on. I'm Ajah Hammerly. I'm on GitHub as Thagamizer, the code from this talk that we posted later today. I need to do some licensing stuff before I can get it out. I tweet as the underscore Thagamizer, assuming that the internet and automation work properly. I have tweeted the slides. And that is going to give you a link to www.thagamizer.com, which is my website, where I blog. And I also have the slides from most of the talks I've given. And I like dinosaurs. I work on Google Cloud Platform as a developer advocate. If you have any questions about Google Cloud, Kubernetes, App Engine, BigQuery, all that stuff, you can come ask me. There's also three of my colleagues are here. Two of them are up here right now and one, I told to go see a different talk so that he could learn from different people. We're also probably going to do a Birds of a Feather or a Lunchtime thing, so watch my Twitter. We'll announce when we figure out when we're going to do that. And since I work for a very large company, LawyerCat says any code in this talk is copyright Google and licensed to PatchEV2. So formality's over, onward. So this talk is based on a class I took my freshman year of college. We called it CS60, although the actual title was the Introduction to Principles of Computer Science. And unlike a lot of CS majors, this course was very early in the major and it was a survey of all of computing. We did finite state automata. We did grammars. We did provability and complexity theory. We did formal logic. But about 10-ish, 12-ish weeks of the course was dedicated to learning four different programming languages, each of which represented a different paradigm and solving the same problem in all of them and solving some problems that were designed for that language. And I learned a lot of stuff from this course. More than any other class I took in my major, this one made me the computer scientist that I am. And the biggest thing I took from this class was abstraction. When I started this class, I knew Java. I knew some Visual Basic and some Basic. But my concepts of things like arrays and conditionals was attached to the syntax for those things. I thought about them in terms of their syntax. And by forcing four completely new languages, three completely new languages, four languages, all in a very short period of time, I was able to move those concepts from being attached to the syntax to actual abstractions in my mind. If you're a philosophy person and you know Plato's allegory of the cave, you kind of have an idea of what I'm trying to get at here. The other thing I took was that I too could be a polyglot. I was always impressed with people who knew a lot of computer languages. But when you learn three new languages in nine weeks and you're able to be productive with them, you realize that once you have the concepts and the abstractions down, the syntax isn't really that hard. And when you're a polyglot, you can point out the similarities between languages. Concepts like conditions and collections and arithmetic and loading and storing things from memory. They show up over and over again in different languages in different ways. And so understanding those at a conceptual level as opposed to I use this syntax for a raise is really helpful. And the other thing it taught me was there are big differences between programming languages. And different languages are good for different things. And I'm hoping that you guys will take some of that out of this 45 minute crash course where I try to cover what I learned in 18 weeks in 45 minutes, I hope. But don't worry if you can't keep up. This is supposed to talk about ideas even though there's a lot of code. So when I took the class, our primary example was solving the puzzle towers of Hanoi with the little rings and the pegs. You have to move the tower from one peg to the other. Explaining the algorithm to do that and then explaining that in four different languages is going to take more time than I have. So we're gonna use something much simpler. I'm gonna talk about change. And by change, I mean this kind of change. In each language, I'm going to show you how you would calculate the amount of change you would give if you were a cashier working a cash register. So everyone following? Let's dive straight in. We're gonna start with OO. We're at RubyConf, so we're gonna use Ruby. I color coded my slides. Ruby is, of course, red. And we're gonna start with something easy. The code gets harder as we go along. It's just how it is today. So let's talk a little bit about OO. Everything in Ruby is an object, everything. False is an object. False is a singleton, an instance of an object. No is an object. Your classes themselves are instances of the object class. Not all OO languages are this pure, but the general idea in OO is that most things, I would prefer all things, are objects. Well, what's an object? An object is a way of encapsulating state and behavior. State is things like fields, attributes, instance variables, what you call them varies a little depending on the language and your particular background. And behavior is what you do with that state, things like methods. Most OO languages, the object is responsible for modifying its own internal state. In Ruby, we call this self. So if I was an object, I could say self.pets equals the array, Emma, Nick, and Shy, because those are the names of my cats. Objects have to interact with each other, because an object just sitting there by itself is rather boring, and the way they do that in Ruby is through message passing. If I wanna find out the length of an array, I send the message length to an instance of an array object that object calculates the length of its internal state and then returns that length to me. So when I'm teaching stuff, I normally try to use my own examples, but since we're going super fast today, I'm going to try to use examples that are canonical or commonplace in the literature, so that hopefully you can kind of attach this to something you may have seen before, hopefully. And one of the most common examples for OO is the idea of a bank account. So I'm gonna build up a bank account object. Well, objects are instances of classes, so class bank account. Bank accounts need to have a balance of some sort, and for a lot of reasons, it's a bad idea to allow folks to monkey with my balance, which is my internal state, so I'm gonna store balance as an instance variable, and I'm gonna set it to zero when I initialize the class, or initialize the object. No, I'm going to talk about money a lot today, and I'm always going to represent money as an integer number of cents. If you are representing money as float in any of your code, come talk to me later and I will teach you about why that is a horrible idea. So, I'm gonna take a break for IRB. I can go bankaccount.new and get an account object back. Now, I know since I wrote the code that my balance is zero, but I can't actually see it, so let's write an accessor. So, I'm gonna have an adder reader, because I don't want anyone outside to be able to set the balance, and that's gonna return balance. Back to IRB, now I can see my balance. It's zero. So, a bank account with a balance of zero is pretty much useless, so I'm gonna add ways to withdraw and deposit money. So, deposit's going to increase the balance. Deposit is a message, it takes an amount, and it adds that to the balance. Withdraw is the opposite, it takes an amount and subtracts that from the balance. And you can see from my IRB break here that it works. So, I talked about an object having both data and methods before. In this case, the data is the balance, and the methods or the behavior are deposit, withdraw, and initialize. And all of these methods modify the internal state of the object, and my IRB process is communicating with them by passing a message like deposit with an amount, and trusting that the object will do the right thing with that data, in that message. So, some of the strengths of OO. It's really good at modeling what we do in real life. So, I have a chair here, I could have a chair object, it could have an attribute color, it could have behavior, hold me up, those kinds of things. We think about the world through concepts and ideas that very closely align with objects. We don't think about the world as the chair's color is fundamentally separate from what it does. Objects are also reusable, a good way to see this is think about the standard library. Arrays are objects, hashes are objects, strings are objects, and we all reuse them in all different ways, because the same types of concepts and objects show up again and again and again in the problems we're trying to solve. And this means I don't have to implement array.length over and over and over. I think objects are easier to test. I can test an object in isolation and test that it modifies its own behavior correctly, and then I can test the seams between the objects when I'm testing my system as a whole. So, on to the motivating example. So I'm gonna do the making change algorithm, OO style. Here's the code. So this is like 28 point font, and I don't expect you to be able to read it. So we're gonna build this up piece by piece. So I have a class, I'm gonna make a class called cash register, because that's what I use to make change. My cash register has a cash drawer, that's the thing that slides out that contains the money. The drawer contains a bunch of different denominations of bills and coins. I have 20s, 10s, 5s, and 1s, and then I have quarters, dimes, nickels, and pennies. If I was doing a more thorough implementation, I could have the amounts of each that I have in addition to the denomination. Here is the method that makes the change, and it's still kind of small, so let's build that up piece by piece too. Here's the method signature. Make change takes an amount owed, this is the amount that the customer owes at the store, and it takes the amount the customer gave the cashier, which you'll see frequently referred to as tendered. Not tender love, Erin. So the first thing I need to do is I need to figure out how much change I have to give the customer, and this is gonna be the difference, and to do that I subtract the owed from the amount tendered, and then I'm gonna represent the bills and coins I need to give the customer in the change array. This is gonna be the thing that tells the cashier, five fives, three ones, blah, blah, blah. The next thing is I need to figure out which part of the drawer I'm working in. When I've seen people make change, a fair number of people start at one end, either the smallest or the largest, and move down the drawer, and grab the corporate amount and then move to the next slot and the next slot and the next slot. So I'm gonna do that exact process with my array that is my drawer, and I'm gonna use I to index where I am in that process. And it's a loop. While I still have change to give the customer, while difference is greater than zero, I'm gonna loop through this thing. So, expanding on the loop a little bit, here's the first part. If the difference, the amount I still need to give the customer is less than the current denomination I'm looking at, the current slot in the drawer I'm looking at. So that would be the case where I have to give the customer $4.50 in change and I'm currently looking at the 20s. I can't give them a 20. So I need to increase my index and set my denomination to the next smallest thing. Now I'm making an assumption throughout the entire talk today that my change drawer is always sorted largest to smallest. If it isn't, none of these algorithms work. And once I've done that I can go back to the start of the loop and try again. So the next part is, now this is the case where I'm giving $4.50 in change with the current thing I'm looking at as a dollar. I'm going to say, well, that's not bigger so I can use that one. So I'm gonna add it to the list of change I'm giving and then I'm gonna subtract that amount from the amount still owed to the client, or the customer. And then I go back to the top of the loop and I keep going through this and eventually I'm going to have the change I need. And this ends up with this method. So those of you who really like your OO are like, this is not OO and you are totally right. This is a really, really bad problem for demonstrating OO. And that brings up the point that different programming languages are good for different things but this is a fine problem for demonstrating the other three paradigms I'm gonna talk about today so that's why I used it. This actually looks much better as a functional program. Onto our second paradigm. I'm gonna use Racket, which is a general purpose programming language in the Lisp family. Lisp in turn, if you have never heard of it, is the second oldest multipurpose high level programming language. Lisp stands for Lisp processor. The only language that is older than Lisp is Fortran. And Racket and Lisp are well suited to demonstrate functional languages although both of them are not limited to that paradigm. You can also use Ruby for functional languages but four languages, 45 minutes. That was the promise of the talk. So, an overview. Functional languages are built of functions. Who would have thought? Functions taken data and output data. I'm gonna focus today entirely on pure functional programming which means that my functions don't ever store state and they don't ever mutate the incoming data. So, if you give me an array, I will give you back a new array and will not modify the one you gave me. So no bang methods if you're still in a Ruby mindset. A nice thing about pure functional style is the input only depends, the output only depends on the input. It doesn't depend on what came before. So I can do a bunch of stuff and then give the same input and it will always be the same thing. History doesn't matter at all. And the really fundamental thing of functional languages is that data and procedures, state and behavior are separate unlike OO where they're encapsulated together. I'm hand waving a bit here. It's not actually entirely true but for the purposes of this talk it is true. So for all the languages that aren't Ruby I get to teach you syntax. The biggest thing you need to know about Lisp family languages in Racket in particular is that we're used to things like in Ruby that use infix notation but Lisp languages in Racket use prefix notation. So to add three and five I use plus three five and you're like, well that's weird but it's actually super useful because I can do one times two times three using only one time symbol which I couldn't do in Ruby. Times one, two, three. That multiplies all those together. I'm not limited to just two arguments which you are with infix notation. And you're like, well that's completely impractical. How can you do multiple levels of it? Well the answer is on the last line there. I'm multiplying three and five and subtracting six from 10 and then I'm adding the two results together. And you just use multiple levels of parentheses and I really like this because the order of operations is very, very explicit. So math is not particularly interesting on its own. I need to be able to write my own functions. You declare a function by putting the word define and then in parentheses the name of the function ends argument list. The square function takes one argument and I'm calling it n. And then after that I have the body of the function. In this case I'm multiplying n times itself. To call that function I go parentheses function name argument square of five is 25. I of course need some way of doing conditionals and I'm gonna use the conditional from a bracket called conned which is short for conditional and it acts like Ruby's case statement. So I have a conned and then the first thing is on the first line is I have a test and then there's some stuff to do if that test is true and then I have a different test and there's different stuff and then there's an else and there's more stuff. Very similar to the case statement. And here's a concrete example. This is calculating absolute value of x. If x is greater than zero well the absolute value of that is gonna be itself so I return itself. If x is equal to zero well the absolute value of zero is zero so I return zero. In all other cases I now know that x is a negative number so I'm going to return the negation of x to give me the positive x. Okay. The only other thing you need to know is lists. As I said lisp, list, processor, lists. This is a list. I represent it as a set of items separated by spaces inside parentheses with a little tick in front. The tick is there because otherwise I wouldn't know if this is applying the function one to two or three or if this is a list one, two, three. Because remember, prefix notation. This is not a function call. When you have lists I can access the first thing in the list by calling the car. These names will come back later I promise. That gives me the first thing in the list or I can get cdr which gives me the rest of the list. You might also hear me to say today head and tail I mean first and rest in those cases or car and cdr. And I can make lists by using cons. In this case I am consing the item one onto the list two, three which gives me the list one, two, three. Some examples. Here's factorial. We use recursion a lot in functional languages. So I have a con if the item I'm trying to get the factorial of is one or less. I return one because the factorial of one and the factorial of zero are both one. Otherwise I multiply n by the factorial of n minus one which recursively will give me the factorial. Fibonacci. This will give me the nth Fibonacci number. So if n is less than or equal to zero I return zero. If n is equal to one I return one. Otherwise I sum the nth minus one Fibonacci number and the nth minus tooth Fibonacci number. That's the definition of Fibonacci. So some of the strengths of functional programming. If I'm doing pure functional programming and I'm not modifying state at all I don't have to worry about all of the stuff you have to worry about with concurrency and threading. Because we're not sharing memory. We're not having to lock tables. None of that stuff is even important because nobody's modifying state. Everything is just a read operation. That's really handy a lot of the time. I think that functional programs are easier to test than some of the other ones because state doesn't matter. Data in, data out, especially pure functional programs which means that the setup for automated tests is just this is the data I'm going to run it on. I don't have to set the state of an underlying object first. And because there's no state you can also reuse this. I can take code that works in one program and throw it in another program and I don't have to worry about there being context around it that's required. And I really like that they're short. Functional programs tend to be really short especially in LISPs. A lot of people hate this but it makes me happy. So, on to our motivating example. Here's the choned code that makes change in Racket and I'm gonna actually slow down a little bit here because I wanna make sure that you sort of understand this. So here's the function signature. It is a function of two arguments. X is the amount of money I need to make change for and denominations is the denominations of bills and coins that are available in my cash drawer. So now I have a conditional. The first case I wanna check is if the amount I'm trying to make is zero I don't owe any change. So I can return a list that is empty because the list I'm returning is what bills I need to pull out of the cash drawer and what coins. So, how do you make change for zero? You give someone nothing, empty list. The next thing I'm gonna check is do I have any money in my cash drawer? If there are no denominations, there's no bills or coins in my cash drawer, I can't make change. So I'm gonna return false. So these last two cases are the tricky ones. So this is the case where the amount I'm trying to make is less than that first domination. So this is car denom's is getting the first element of the denom's list which is the highest bill in the cash drawer that I'm currently looking at right now. If that amount is less, sorry, is greater than the amount of money I'm trying to make, I need to use the rest of my cash drawer. So if I'm trying to make change for 450 with a $5 bill, I can't do that. I need to use the rest of my denominations to make change for acts. So I do a recursive call. Finally, and this is the case where I actually use that first bill. So remember, I'm trying to return a list and I make lists with cons. So I'm conzing the first element of my denominations thing which might be my $5 bill onto the recursive call to make change for the rest of the amount. And I calculate the rest of the amount with that subtraction there. That's like that difference equals line in the Ruby. And then the same set of denominations I'm working with because I might need two or three pennies. I might need to use the same denomination more than once. So this is the case where I don't use the current thing I'm looking at. This is the case where I do. There's really only two cases beyond the base. So I really, really like this. It's much shorter than the Ruby. I think it's very, very logical. And if you've got some background in number theory or mathematical theory and you're used to proofs by induction, I think the recursion looks very familiar and very comforting. But this is not actually the shortest solution to this problem that we will see today. That is given to my friend Prolog. We're gonna do logic and constraint programming. And this is going to most likely be by far the most brain-breaking part of the talk. So I will try to take it slow and you can come up and talk to me about Prolog later. I'm happy to demonstrate all this code. So I'm gonna give an overview of Prolog. Prolog is based on formal logic. Things like Socrates is a man. All men are mortal. Therefore Socrates is mortal. So ands, ors, implications, knots, that kind of stuff. Very, very basic formal logic that's used in philosophy and mathematics and also is the basis of a lot of computer science. Prolog programs aren't made up of instructions. They're made up of facts and clauses. Yes, that's weird. And the weirdest thing about Prolog is that instead of describing the how, we're used to in programming telling the computer how to solve the problem, Prolog works different. You describe the what of the situation. One of the common examples is a logic program. So I would say, okay, the logic program says that the guy in the yellow house does not own the fish. And I would encode that, or I would say that the guy who really likes to drink rum lives next to the man who owns the cat. And I can encode all of those facts in the system and then what Prolog does is it uses everything that it knows and it tries to come up with a world where all of those are true. And it fills in any blanks that are remaining once it comes up with the world where all of those facts and clauses are true. So a syntax to do this is a little weird. The biggest thing is that we have variables and constants. Variables start with a capital letter. Constants don't. This is our lowercase letter. And then we have facts and facts end with a period. So I can say that Washington is a state or that Washington borders Oregon and Washington borders Idaho and Oregon borders California. And using this I can define a rule and rule specify relationships between facts. So here I'm defining the rule adjacent and that colon minus sign is actually a logical implication. If you know what that means that might help you understand this. But all this is saying is that x and y, now those are variables because capital letters are adjacent if there is a fact where border x and y is true. And what Prologue's gonna do with those variables is it's gonna try to pattern match. It's gonna go through all of the facts it has and figure out if there's some constant it can put in for x and another constant it can put in for y or the same constant where there's a rule that matches or fact that matches. And this is called pattern matching and pattern matching languages are awesome. And so here's my adjacent rule again. Now here are the facts I have, some of them. And here's the adjacent rule and I can go into an interactive Prologue terminal and say, hey Prologue, is Washington adjacent to Oregon? And it will say yes. And then I can go, hey Prologue, is Oregon adjacent to Washington? And Prologue's gonna say no because Prologue is incredibly literal. And since I only have a fact that says that Washington and Oregon share a border, not that Oregon and Washington share a border, Prologue doesn't know that the reflexive case is true for this particular rule. So I have to teach Prologue that by saying that adjacent x y implies that there is a border between x y, but adjacent x y can also imply that there is a border between y and x. I got a tricky there. And then if I go in and say, hey Prologue, is Oregon adjacent to Washington? Prologue will correctly say yes. And I have a couple minutes so I'm gonna go over my favorite Prologue joke. How many Prologue programmers does it take to change a light bulb? Anyone know? No, the answer to that is no. So I'm gonna do some basic examples and the canonical example in Prologue is ancestors, building a family tree. So I'm using the Simpsons and one of my first rules is that first facts is that father, homer, Bart. So that's saying that homer is Bart's father. You have to change the word order around a little bit to make it work in English. Not true in other languages that have different word order than English. I can also say that homer is Lisa's father. I can say that Marge is Bart's mother and Marge is Lisa's mother. So then I can go into my interactive Prologue terminal and I can start asking questions. I can say, hey Prologue, who is Bart's mother? And that's that first line there and what I'm actually saying is, hey Prologue, what do I need to shove in for X? What value of X makes this statement true? And Prologue's like Marge is Bart's mother, which is correct. And then I can say the opposite. Hey Prologue, who is Marge the mother of? By putting the variable in a different location. And Prologue says Bart and then I can use the semicolon to say, you got anything else? And Prologue will say Lisa. And this is the real strength of Prologue is that I can run programs backwards and forwards and I can put variables wherever I want. And it is crazy the first time you do this. But it's also super duper powerful. And I've showed you simple examples thus far, but you can build rules that are much more complicated. So let's build the rule sibling. So X and Y are siblings if there is some Z such that Z is the mother of X, Z is the mother of Y and X and Y are not the same person because you can't be your own sibling and that slash equals equals is not equal in Prologue. But there's another way that you can be siblings. X and Y are siblings if there is some Z such that Z is the father of X, Z is the father of Y and again X and Y are not the same person. And Prologue's gonna try to figure out whatever values it has to put into each of those capital letter variables to make this true. So I can go into the interactive Prologue terminal and say, hey Prologue, who are siblings? And it says, oh, Bart and Lisa are siblings. Awesome. So I'm gonna go into the last bit and this is one of the most complicated bits of Prologue that we're gonna talk about today. Prologue has lists like Rackett, like Ruby. I have an empty list, I have the list one, two, three. I have a list apples and bananas. So I can have lists that are heterogeneous. I can have lists that have numbers or constants in them. And I can also have nested lists which is what I'm showing on that last line. But in order to pattern match on lists, I have to have crazy, some crazy notation. This is called bar notation. I'm gonna say this aloud as F bar R. You can think of the F as first and the R as rest. And this is just like the car in the cutter we saw in Rackett. F is the car, it is the first element of the list. The bar separates the first element from the rest of the list, which is the cutter. And if that didn't make any sense, if I have the list one, two, three and I pattern match that against F bar R, F is going to match the one and R is going to match the list two, three. So car and cutter, same thing, crazy notation. The last little bit is this is an underscore. So I might break some of your brains, I hope not, but did you all know that you can use the underscore to say I don't care about this variable, it's unused in Ruby? And good, people are nodding, this is fantastic. I've broken people's brain with that one before. Rackett has the same thing and underscore in Rackett is called meh, I like that. Learn that from Ryan Davis last night. And then in Prologue texts, we refer to this underscore as don't care, which is this variable isn't actually used for any of the logic, so put whatever you want there, I don't care. So we're gonna do a quick list function, list rule, not a function, not in a functional language. So this is member, it's like include question mark in Ruby. So x is a member of the list. First argument is the thing I'm looking for, the second argument is the list, x is a member of this list, if x is the first thing in that list, makes sense, right? That's one case, oh, forgot to change the bold. Second line, x is a member of this list, if, I don't care about the first thing, doesn't match, but x is a member of the rest of the list. So x is a member of this list implies that x must be a member of the rest of the list. So recursion, it's handy that way. So strengths, one of the awesome pro things about Prologue is that thing I mentioned about running programs backwards and forwards, this is true of logic programming in general. There's a great talk about Minikanron where they actually run their logic system backwards to generate the code for factorial. Because why not, you can run it backwards and forwards as long as you set up the constraints correctly. One of the early use cases of Prologue that I've read about was actually scheduling time to use limited resources in a research lab. I believe the research resource was a dolphin and they needed to figure out how do you work everyone's schedules around, like this experiment's gonna take 45 minutes and we need to repeat it every three days for a month and I have class at this time and all that. They used Prologue to put all those constraints in and solve the problem so that they had a reasonable shift schedule. So, time to make some change. So, we're in Prologue. The weirdest thing and the thing that always gets me when I have to contact switch into this language is I don't have a return. There is no concept of a return. Everything is encoded in the method signature and you have to have that so you can run it backwards. So, we're gonna have a change rule. It has three arguments, the first is the amount, the second is a list of coins or bills we have, and the third is how you make change for that amount using that list of coins. First one is an integer, the second two are lists. So, this is going to be true only if change, that last argument, is how you make change for the first amount using the coins in the middle. I think it might have just snapped for a couple of people. This is weird. So, here's the code for the change function. It's actually shorter than the racket. We'll go through it, I promise, I promise. So, first case, the easy case. How do I make change for the amount zero? Well, change for the amount zero is the empty list and I don't care what's in my cash drawer, which is why I'm using the underscore, because I don't need to know, I don't need to use anything from the cash drawer if I'm making change for zero. That's the easy one. Here's the second one. Focus just on the first line right now. This is where we use pattern matching. So, I've got an amount a and this is saying that I make change for the amount a by using the first thing from my cash drawer and that is the first thing in the way I make change. So, this is the case where I use that first bill or coin in the cash drawer. And I can only do that if the amount is greater than the denomination of that first thing. And if those two things are true, I need to calculate b such that that is the difference between the amount, that is what's left over after I use that bill. And the other thing that has to be true in that case is that I can make change for b using the same stuff in my cash drawer and the way I do that is x, which matches that x on the very top there. So, a is greater than f. I can use this because the bill is smaller than the amount I'm making. b is equal to that difference, the remaining amount of change, and the way I make change for b is x, which matches on that top part. Remember, Peralg is gonna make all of the instances of each variable the same thing. So, that's the second clause. Third clause, this is the case where we don't use the first coin or bill. So, I used a don't care again. I only wanna apply this one if I'm actually making more than zero in change because if I'm making just zero, I can use the first one above, the very first one. And in this case, I'm gonna say, hey, the way you make change for a is you use the rest of the stuff in your cash drawer and the way you do that is x. So, this is the other recursive case. And I promise it works. And you're probably going, ow, my brain right now. This, I love Peralg, and this was the hardest of the examples for this talk to write. I actually had to break into the debugger to do it. And I didn't have to do that for even what's coming next, which is a procedure role. And we're gonna do that with assembly. So, the fact that I was able to write the assembly without the debugger and I needed the debugger for the prologue, the prologue is hard. So, assembly is old school programming. We have a limited vocabulary, a limited standard library, a limited number of functions we can call. And by limited, I mean very limited. For the assembly I'm using, I think there are less than 30, I think there's like 22. And there are tons of assemblies that exist. I am using the assembly from a book called, well, it's commonly referred to as NAND to Tetris. I have a bibliography entry for it in NAND so you can grab it and look, check it out yourself. The reason I'm using this is that it is less ugly than most assemblies, it looks more like the programming you're used to. And it's very, very simple. So, here's the syntax. So, the big thing about the assembly is that I have two registers, A and D. And those are the only two things that I can do operations on. D is D because it is the data register. A is A because it could be a data register or it can be the address register. And when it's the address register, I use whatever value is in A and I go pull that cell out of memory. So, in the cases where I'm using A to access memory, I'm gonna actually just call it M. So, I'm gonna use A, D and M, but I only have two. It's just when I'm using M, I'm using what A is pointing to and when I'm using A, I'm using the actual value of A. And circling back to Racket, we had car and cutter. Car stands for the contents of the A register. Cutter stands for the contents of the D register. That's where the names came from. So, we got some computations. I can do A plus D. I can do D minus A. I can do A minus D. I can do A plus one or D plus one. I can do A minus one or D minus one. I have a bitwise not, a bitwise and and a bitwise or. And I can negate A or D. And any place I use A, I can also use M. So like M plus one or D plus M. And that's it. That is the contents of the list of things I can do. And important to note, I don't have multiplication. Don't have division. Don't have anything that even remotely looks like a list. Very, very limited. But I can actually assign the things I calculate to values. So I can assign to any of the registers or to memory. So I can say D equals M plus one or D equals D minus one. And I can also do multiple assignments. So I can say M and D both get the value of A plus one. Which is crazy, because then I'm incrementing the memory register, yeah, that's a bad idea. I need to be able to get constants into my program. And the way I do that with this at syntax, and constants only can go into the A register. That's why it's at. So if I wanna load 100, I do at 100. If I wanna have a kind of label, and I use this label somewhere in the program to access the line of my program that this label is on. And again, since this goes into the A register. And I use this for jumps. Jumps are this format. There's a value, a semicolon, and then the type of jump. And so I'm like, the value in this example is D. J, G, T is jump greater than. And I will jump to whatever line of the program is in the A register if D is greater than zero. I don't get to have any other greater thans. It's always been referenced to zero. So I have J, E, Q, jump if equal. And so this will always jump, because I'm jumping if zero is equal to zero. Jump greater than, jump less than, jump greater than or equal to, jump less than or equal to. I also have a non-conditional jump, which is J, M, P. So those are the jumps I have. Those are the only form of branching logic I have in this entire language. So here's how we add. This loads at two into the A register. I then move the contents of the A register to the D register. This loads at three into the A register. And I add what's in my D register to my A register and assign it to myself. And then I take whatever is there and I assign it to the contents of memory cell zero. And it's memory cell zero because I put a zero into the A register. And then I'm using an M, which means it refers to memory, not to the value in A. See, it's easy. Here's how I sum the digits from one to five. I'm actually doing it backwards. So the first thing I do is I'm gonna store them, I'm gonna store my result in memory cell zero. So I wanna zero out memory cell zero. And then I'm gonna store five in memory cell one. So I load it into A, assign it to D, and then load address one into A, and then assign whatever is in D, which is five, two, memory cell, that's referenced by the address in A, which is one, so putting in memory cell one. Here's my loop. The parentheses notation is a label. First thing I do is I pull whatever is in memory cell one, which is five in this case. And I put that in D. And then I'm going to take whatever I have in D and add it to the contents of memory cell zero, which is my accumulator. So now it's memory cell zero is five and memory cell one is five. And then I'm gonna take the contents of memory cell one and I'm gonna subtract one from that. So now I've decremented to four. And I'm gonna store that in both back in my memory cell one and in D. And then I'm gonna do my logic. And here's my loop. So I'm gonna load end into my A register. This is where I wanna go and it's the end of my program if my program's over. And I know my program's over when my counter has gone from five to four to three to two to one to zero. And so if D is less than or equal to zero, I'm gonna jump to the end. Otherwise, I fall through to my loop label and I'm gonna go back to the top of my loop in all other cases. And I guess I have an unconditional jump there. Awesome. So strengths, there are no strengths. I don't have use for assembly on a daily basis. I'm really hoping that none of you do too. But procedural style in a self can be useful and you can write procedural style in any language. Most of us, our very first program was procedural. Hello World is totally procedural. All of the scripting stuff we write is generally procedural. Do this thing, then do this thing, then do this last thing. And writing procedural code is generally pretty easy. For most of us, our brains instinctively think this way. So here's making change in the assembly. So I don't have lists. So I'm gonna use memory zero for the amount to make. I'm gonna use memories one through four for my coin denominations, 25, 10, five and one. And I'm gonna use memories five through eight for the number of each coin D is. Cause I have memory, we'll turn it into a list. The assembly I'm using doesn't understand this M syntax, it uses R instead. So you'll see this in the code. So this loads 67 into memory register zero. And then, yes. And then this loads the denominations. And then this is the code for quarters. So I load in my, I load in the amount I wanna make. I load in the amount of the quarter is. I subtract the amount that a quarter is from the amount I wanna make. If the result is negative, I don't need any quarters. So I go on to dimes. If the result isn't negative, I save the amount I have left, increment the number of quarters I've used and go back to the top. So I didn't cover anything in detail. And I've got four minutes left according to my timer. So let's do this thing. So here's where you can learn more about functional. Talks by Jim Wyrick, including his Why Not Adventures in Functional Programming Keynote from RubyConf 2012. Again, I tweeted the slide, so you don't have to take pictures of this. The slides are online. And then, Freedmen and Filiasen have the Little Schemer, the Reason Schemer and the Season Schemer. Those are fantastic books. They're written in Socratic Dialogue, they're awesome. And the Structure and Interpretation of Computer Programs is a very large textbook on the fundamentals of computer science from a functional perspective. I gave a talk at Cascadia Ruby 2012 on Prolog. It's the 45-minute version and much easier to follow than this talk. There's also the Art of Prolog, Clause and Effect, the Prolog Programming for the Working Programmer, and Prolog Programming for Artificial Intelligence. And then I mentioned that the assembly I used was from a book called Nandetetris. The actual title of the book is the Elements of Computing System, Building a Modern Computer from First Principles. I highly recommend, if you don't understand how your wizard box works, you follow this book. You start with logic gates and you end up writing a very small version of Java, including the assembler, the machine code, and the VM underneath. It's awesome. And if you just like languages, seven languages in seven weeks is the classic, and then I also have, and it's actually in my bag, a book called Exercises and Programming Style, which is basically this talk, but in book form and better. It goes over lots of different styles and how to do the same program in lots of different languages. I have it with me, come find me, and you can flip through it. So I'm supposed to have a thoughtful closing here, but I'm out of time because I used every last second I had available. And I also kind of told you what the whole purpose of this talk was up front. You can learn other programming languages. Other paradigms are not that different. Everything has conditionals, accessing memory, integers, mathematics, it's all similar. So go learn other languages. Because it's me, I have dinosaurs, you can come get one later. There's a bunch on a chair up front, and I have special edition Mardi Gras dinosaurs for RubyConf New Orleans. I also have Google Cloud stickers and I'm done. Thank you. Thank you.