 Who's ready for 200 slides of code in 45 minutes? My talk's called Four Programming Paradigms in 45 Minutes. This is the result of me proposing a talk that I didn't want to give, and then them saying, that sounds awesome. We should do that. So I don't recommend that strategy. I'm Aaja Hammerly. I'm on GitHub as Thagamizer. I tweet at The Thagamizer. And I did not include a picture of my cat in this talk. But if y'all ask good questions afterwards, I will tweet out a picture of my really annoying cat who let himself out of the house by opening the door and then got lost for three days recently. And I blog at thethagamizer.com. And I just released a new blog post on bad managers. So if that's the kind of thing you're interested in, you might go read that. The slides for this talk are also on that domain if you have bad eyesight and can't see the code on the screen, or if you just would rather follow along on the home version. And I like dinosaurs a lot. So if you're interested, I work for Google Cloud Platform. I'm a developer advocate. So if you're interested in Google Cloud, if you've heard of that thing called the Kubernetes and you don't know what it is and want to chat about it, or if you want answers to questions or opinions about the cloud, I'm happy to share many of those things with you. Come find me in the collaboration room or during breakouts. And since I work at a large company, Lawyer Cat says any code in this talk is copyright Google and licensed Apache V2. So this talk is about celebrating polyglots. From the outside, programming seems like very prescriptive and systematic and perhaps even boring. But well, programmers, and we know that there's a lot of variety and creativity in programming. There are many, many ways to solve a problem. And there are many schools of thought or paradigms in the programming world. This talk is about the similarities between languages, concepts like conditionals, collections, assignment, arithmetic. But it's also about the differences. Different programming languages are good for different kinds of problems. And knowing a lot of different kinds of programming which can help you understand the abstractions that underlie everything we do in our day-to-day life as programmers. When you have these abstractions, you're no longer attached to syntax. And that means that your brain can be more flexible about ways to solve problems and you can learn new languages more easily. If anything 15 years in the industry has taught me, is that I'm going to have to learn a lot more languages over the next 15 years. So in order to show the similarities and differences between languages, I'm going to show the same example in four very different languages. And that example is making change. Specifically, I'm going to use each language to calculate how many coins and bills you need to give a customer to make change or to make up a certain amount of money. So with that, let's dive right in. Ruby hack. So we're going to start object-oriented. And of course, we're going to use Ruby. And the slides are red because Ruby. Quick overview. You all probably all know this, but just to make sure, everything in Ruby is an object. Nail is an object. False is an object. True is an object. Some of you may not know. False and true are actually singleton instances of the true and false class. Objects contain state and behavior. State is like things like fields, attributes, et cetera, depending on the language. Behavior is what you do with that state. Most likely, methods. And in Ruby, we refer to the object itself as self, and that's how we modify our own state. For example, self.pet, my cat is named Emma. Objects interact with each other through message passing. If I want to find out the length of an array, I send length method to a specific instance of the array class. The array object that I send it to calculates its length and then returns that to me as an integer. When I'm teaching stuff, I usually try to use my own examples because I find most textbook examples really boring. But it's a lot of material I'm going to cover today. And so I'm going to use the canonical examples where I can so that if you want to go deeper, you have something that you've seen that's familiar when you go to read the textbooks and stuff that I will recommend. And one of the most common examples for OO is the bank account. Basically, let's build a bank account. Objects are instances of classes, so I start by creating the bank account class. Bank accounts need to have a balance associated with them for a lot of reasons. It's a bad idea to let folks monkey with the balance. I'm going to make it a instance variable and I'm going to not have any accessors for it. And I'm going to initialize the balance to zero when I initialize the object. Side note, I'm representing the balance as an integer number of cents. If you think using floating points from noni is a good idea, come find me later and I will tell you why you are so very, very, very wrong. Floating points are not accurate enough. So throughout this talk, money is always gonna be represented as an integer number of cents. So quick break for IRB. I can instantiate my object and I know it has a balance of zero since I just wrote the code, but I can't see that outside the object. So I'm going to add a reader, not an accessor, a reader to see the balance. Now I can instantiate the object and then I can see that its balance is zero. Now we add deposit which increases the balance and withdrawal which decreases the balance. And again in IRB, I can deposit 100 cents a dollar to withdraw 30 cents and have an balance of 70 cents. If I was doing this for real, I'd probably add a code to prevent overdrafts, an account number, maybe some other things as needed, build some sort of crazy double entry display for it to make it all look fancy and official, but I've got three other paradigms to get through. So I talked about objects as having both data and methods before. In this example, the data is the balance and it's set and initialized, but also deposit and withdrawal all interact with that data. They're all modifying the internal state. My IRB process communicates with them by sending the deposit, withdrawal or balance message and then the object sends the results back. Strength is about, oh, the big one is modeling. The world around us is composed of things like my clicker or the seats you're sitting in or the projector's up there and it's also composed of ideas like happiness. And all of those exist in the real world and we can use objects to model most of those things. And if you have your data and your methods encapsulated together, it's really easy to pick that up and put it elsewhere. So I don't have to write the code for calculating array length every single time I wanna have a collection object. A lot of people really like the ease of testing that comes from objects because you can test each object independently and then you can test the system as a whole once you know that each of the individual pieces are working. So onto the example, making change your style. So this is the code for a cache register and you can't actually see that in the back. So let me build it up piece by piece. The class declaration and the initialization, I have an instance variable drawer which represents my cache drawer. I have 20s, 10s, 5s, 1s, quarters, dimes, nickels and pennies in the cache drawer. And for all of my examples, I'm going to assume that the cache drawer is sorted because that's how we keep cache drawers. It also makes writing recursive code really easy. So here's the make change method. Make change takes an amount owed in the amount the customer gave you which I'm calling tender. I then calculate the difference which is the amount of change I need to give back and I create a change array which is where I'm going to store the exact bills that you need to hand over. I'm going to have a variable I which is the current slot in my cache drawer I'm looking at and I'm going to have a denomination which is the amount that is in that place in the cache drawer. I normally wouldn't do this but it makes code on the slide much easier to understand. So while I still have money to give back to the customer, I'm going to loop through this. Inside the loop, I'm going to see if the difference, the amount I still need to make is less than the denomination that I'm currently looking at. So if I'm trying to make $7 and I'm currently looking at the tens, I can't use a 10 to make change. If that's the case, what I'm going to do is I'm going to increment my index and move to the next smallest thing in the drawer. In this case, that would be ones looking at the fives or tens, sorry, tens, trying to make $7 increment moves them down to the fives. Yes. And then I'm going to start from the top of the loop again. Now, if I'm trying to make $7 and I'm currently looking at the fives, I can use that. So I'm going to add that to my change array and then subtract $5 for my difference that I still need to make. Awesome. Simple is super easy. So who's experienced with OO before? I should see lots of hands. Please, please show me hands. So you're probably thinking, that's a horrible example for teaching OO. Azhar, why did you do that? And the reason is is that, yes, this is a horrible example for teaching OO, but it's much, much, much better example for the other three paradigms I'm going to teach you. So let's drive straight into functional programming. I'm going to use Racket. Racket is a general purpose programming language in the Lisp Scheme family. Lisp, in turn, is the second oldest programming language and Racket and Lisp are really well-known, Lisp especially, but Racket, increasingly, is a really well-known functional language in a great way to demonstrate it and it has lots of parentheses, and I like parentheses. So, functional languages. Who would have thought? They're made up of functions. Functions taken data and output data. I'm going to be doing all my examples in this talk is pure functional. That means I won't ever store or mutate the data at all. As one of my previous coworkers said, mutable state is fundamentally suspicious and cannot be trusted. The nice thing about pure functional style in programming is that the output only depends on the input. There's no state. So if I give the same input to the function every single time, I'm always going to get the same results. Data and procedures are separate in the functional languages. They aren't combined together like they are in OO languages and I will acknowledge right now for those of you who are going, that's not true, that I am hand waving pretty vigorously here, but that is true for the purposes of this talk. So, syntax. Racket uses prefix notation, which is going to look a little weird to some of you. The name of the function is the beginning of the function call. Probably more used to infix notation. But prefix notation, if I want to add three and five, I call the plus method with the arguments three and five. The parentheses make it a function call and I get back eight. And the nice thing about prefix notation is that it's very easy to take an arbitrary number of arguments. So multiplication, multiplying one, two and three, it's just as easy as multiplying one and two. I can just shove something into the end of the argument list. It gives me six. The other nice thing I like about prefix notation is it makes the order of operations really clear. Here I'm multiplying three and five, subtracting 10 from six and then add, I'm subtracting six from 10 and then adding those together. And I don't have to worry about operator precedence and binding, which binds closer and anything like that. The parentheses and the notation make it very clear what's going on. I can't mess it up. But I said functional languages have functions. So here I define a function by calling the word define and then putting the name of the function in the argument list inside parentheses. And then the body of the function is this case times n times n because I'm defining square. And then I spend the whole thing in parentheses because yay parentheses, that's just how lists work. And then I call the function by parentheses function name argument list five in this case and it returns 25 because that's the square of five. It gets weird or don't worry. Conditionals, I'm going to use cond, although there's a lot of other conditional constructs in racket, cond is short for conditional and it acts like Ruby's case statement. So I have a cond, it's surrounded by parentheses because parentheses, then there's each clause, the first part of each clause is a test. And then there's the stuff you do if the test is true and if that test isn't true, you go to the next test. And then if the difference is true, you do different stuff and then there's the else for none of my tests were true so I'm going to do yet some more stuff. So here's an example, absolute value. First condition, if x is greater than zero, I'm just going to return x, that's the absolute value. If x is equal to zero, I'm going to return zero. Otherwise I know x is negative so I'm going to return the negation of x. Simple. Lists are collections, think about them like arrays. Items separated by spaces inside parentheses. You might be thinking, what's with the back tick? Well, if I didn't have the back tick, this would be calling the function one on the arguments two and three, which doesn't actually make a lot of sense. So you put the back tick there to know that this is a list literal. I love lists. So car gets the first element of the list or the head, in this case one. Cudder gets the rest of the list, in this case the list two, three. We will come back to car and Cudder in just a little bit and I will explain to you why they have such crazy names. And cons used for making pairs. So in this case I want to add one to the list two, three. I cons them together and I get the list one, two, three. So quick example, factorial. Define the function fact n. I have a conditional. If n is less than or equal to one, I return one because that's the definition of factorial. Otherwise I multiply n by the factorial of n minus one. Simple. Fibonacci. If n is less than or equal to zero, I return zero. If n is equal to one, I return one. Otherwise I add the Fibonacci recursive call of n minus one and the Fibonacci call of n minus two because that's the mathematical definition of Fibonacci. So strengths. One of the fantastic things about your functional style is that if you don't mutate state, you don't have as much constraints when you have concurrency because you don't have locking tables or shared memory or race conditions or any of that other stuff that causes those problems. I figured out what's going on, that might up there. It's also easier to test. If you only put the same input data and always get the same output data, it's much easier to figure out what you need to test. You don't have to do any setup for setting up state. And it's very easy to see from the code exactly what your cases are. And code that contains no state is safe to reuse anywhere. So reusability is awesome. I like functional programming a lot and I like it because it's very, very brief. Others hate it for the exact same reason. So making change functional style. You can see much shorter than the Ruby version. You can actually probably read that in the back. But let's walk through it. To find my function, make change. X is the amount I need to make and denom is the denominations that are in my cash drawer. If X is equal to zero, if I don't actually need to make any money, well, I'm gonna return a list that is empty because don't give them any bills. Makes sense. If my cash drawer is empty, I can't make change. So I'm gonna return false. There's two recursive cases. The first one is the case where the amount I'm trying to make is less than the denomination that's at the beginning of my denominations list. So this is the case where I'm trying to make $7 and I'm currently looking at the tens. In that case, I'm just gonna call it recursively and use the rest of the stuff in my cash drawer with the same amount. And then the fun case. If the amount I'm trying to make is not less than the denomination I'm currently looking at, so I'm still trying to make $7, but now I'm looking at the fives. I'm gonna take one of those fives, I'm gonna add it to a list that is making the rest of the amount. That's what that minus X card denoms thing is and my cash drawer. Simple. Don't worry, it gets weirder. We are on to our third paradigm. We're gonna do logic and constraint programming. We're gonna do it with prologue and I promise you I will tell you my favorite prologue joke at the end of this, but I cannot promise you that it is a good prologue joke. So prologue is a logic language used for constraint solving primarily and it's based on formal logic. And by formal logic, I mean things like all men are mortal, Socrates is a man, therefore Socrates is mortal. And formal logic is at that beautiful intersection of mathematics, computer science and philosophy because clearly all of these things are friends and we should all hang out together. Prologue programs are made up of facts and clauses and the really brain-breaking part of prologue that gets most people completely confused and wanting to run away is the fact that you never tell prologue how to solve a program. Prologue figures that out for you. It's actually just searching a possible constraint space. Instead you have to describe the problem in very explicit detail so that prologue can then figure out how to solve it itself. So let's say you're solving a logic problem, like the guy in the blue house has the fish and the guy in the white house really likes to drink Pepsi. Like you're trying to figure out where everyone lives and what their pet is and what their favorite drink is. In prologue, you don't tell it how to do a depth first search of the search space. Instead you just carefully enumerate all the rules and constraints and then say, hey prologue, can you solve that for me? Which is really, really weird for all of us who've been taught programming using the, this is how you make a peanut butter sandwich method because that's not how prologue works. So the syntax isn't actually not too bad but since we don't need a lot of operators it's not actually that complicated and it's a little weird. We have variables, internal caps and we have constants which are in lowercase and that's pretty much it. I can define facts, facts and in periods. So I can say that Washington is a state I can say that Washington and Oregon share a border and that Washington and Idaho share a border and that Oregon and California share a border and then I can say, hey prologue, let's make some rules. Rules are a set of what look like facts but basically what's saying is that X and Y are adjacent X and Y are variables, remember capital letters and then there's that colon minus thing that's actually a logical implication. Normally I leave that out when I talk about this with people but every time I've spoken in Salt Lake the level of background in mathematics and computer science has been really high so maybe that'll help y'all. That's a logical implication and what I'm saying here is that two states are adjacent if they share a border and if the border rule is true. So adjacent is true if everything on the right hand side is true. And what prologue does is goes and does some crazy pattern matching. I love pattern matching languages, they make me so happy. My pattern matching what it's doing is it's actually doing a process called unification but that is the only time I will say unification in this talk if you wanna hear more about unification stay tuned to the end and I will give you resources where you can learn about that. So prologue's gonna go try to find some values for X and Y such that the rest of them on the right hand side is true. So I'm gonna say prologue or Washington and Oregon adjacent. Prologue's gonna say yes because that's what prologue does. It says yes and no primarily, it's fantastic. And then I'm gonna say prologue or Oregon and Washington adjacent and prologue's gonna say no, which okay, why'd that happen? Well prologue is incredibly literal and I did not tell it that my adjacency rule is reflexive. So if I wanna fix that, I have to add a second rule where I say adjacent X, Y is also true when there's a border fact for Y and X because prologue. So some basic examples. The classic prologue example is specifying a family tree. Yay. Here I'm saying that Homer is Bart's father and Homer is Lisa's father and Marge is Bart's mother and Marge is Lisa's mother. Then I can say, hey prologue, put the variable in constant in Bart, who is Bart's mother? And it's gonna say, hey, I was able to make that true by saying that X is equal to Marge. I can also say, hey prologue, who is Marge the mother of? And it will say, well, Bart, and I can say, hey, you got any others? And that's what that semicolon means is yes and and then it will also say, hey, Lisa also makes that rule true. Which means I can then define relationships like this. X and Y are siblings. If there exists some Z such that Z is the mother of X and Z is the mother of Y and then that crazy slash equals equals syntax is actually not equal because you're not really your own sibling. That would be weird. So X and Y are siblings. If there is some Z where X is the mother of Z and Z is the mother of X and Z is the mother of Y and X and Y are not the same. X is also a Y sibling if there is some Z such that Z is the father of X, Z is the father of Y and X and Y are not the same. So then I can say, hey, from our list of rules, hey Prolog, who are siblings? And it will say Bart and Lisa. Lists, Prolog has lists. Most languages have collections. It's some stuff in square brackets with commas and they can be mixed type. Looks like Ruby, yay. But dealing with lists in a pattern matching language gets a little complicated and Prolog uses this lovely Bart syntax that I adore but confuses people. So this is pronounced F bar R and F matches the first element of the list and R matches the rest. This is just like a car and cutter that I showed you in a functional programming. So if I have a list one, two, three, if I have pattern match that against F bar R, F is gonna be equal to one and R is going to be equal to two, three. But they're not actually equal, they just match because equality is not really a thing in Prolog. And the last thing I need to show you is that Ruby, just like Ruby and Racket, underscore is the I'm not using it variable which I was informed is also pronounced me. So in Prolog text, you'll also see this as referred to as the don't care variable. This is the unused argument variable. So member, member is like include and if you wanna use the pronunciation of include for that I learned from my Canadian friends, it's include a from Ruby. So this is member, there's only actually two rules. The first is actually a fact. X is a member of something if X is the beginning of a list. Sure, why not? X is also a member of something if there's something I don't care about at the beginning of the list and X is a member of the rest of the list. Okay, sure. So strengths of Prolog, the big thing is the flexibility. So I just showed you a member. So I could use that to detect if a number was in a list but I could also use that to generate all of the list that contain that number because you can run Prolog backwards. There's a really great talk using mini-canron which is another logic slash constraint programming language where they generate all of the racket programs that will return a result of 120 when given an input of five, trying to generate factorial. Think about that for a second. They're generating the code by running the program backwards. It's amazing. Prolog is also great for problems that involve constraints. If you've ever tried to do like a table planning for a wedding and you're like well I can't have these two people on the table because they know they're gonna cause problems trying to figure out how to make everyone work and the tables only see this money except this table to only seat six and the rest seat 10 and all that. Prolog is great for that. One of the examples I learned about from doing my research is that there was a research lab where they were trying to schedule use a shared resource which I believe was a dolphin and they were trying to do it around people's class schedules and work schedules and also make sure that they had enough time for the dolphin to rest and they didn't have enough activities on the same page and they ended up using Prolog for that. So making change in Prolog. Prolog doesn't have return values. I haven't actually hinted at that recently but it doesn't actually have return values. So you need to encode the return value into your rule. Our change rule has three arguments. First is the amount we're making. Second is the coins or bills we have in our drawer. And third is the amount of change to give. Those last two are gonna be lists. And this is the entirety of the code. It's even shorter than the racket version. First rule, if I'm trying to make no money I don't need to actually give you anything back so I don't care what's in my change drawer and I'm gonna give you the empty list back. Okay, sure. Second rule, this is the case where we are not using, this is the case where we are using the first, the amount that's at the current spot in our change drawer. So I'm gonna say we're gonna have A which is the amount. If A is greater than or equal to the first element of our change drawer, F and B is A minus F, not equality, logical equivalents. There's no assignment happening there in the sense that we think about it. Then we wanna make sure that the change we give is gonna be the change for the amount B with the same list of denominations making the list X. So this is really confusing. But the big thing we're doing here is we're doing a recursion. We're taking the amount we need to make still and we're saying that that amount is going to be made with the bills associated in the list X and then we're shoving them back in that first line using the bar notation to construct a list instead of deconstruct the list this time. Don't worry, it gets better. And then the last example is the case where we're not using the first thing in the drawer. In this case, we're gonna say we have an amount A. We don't care what the first thing in the drawer is and we're going to say we make that using the list X. If we need to make sure that A is greater than zero X Prologue will happily go try to make a change for a negative number. And then we do that by calling change recursively on the amount, the rest of my change drawer and the list of bills we wanna make X. So how many of you are thinking, ow my brain right now? Yeah, I love Prologue but even the fact that I love it and it's one of my favorite languages of all the examples of this talk including the next one, this was the hardest to write and this was the only one I actually had to break into the debugger to make it actually work out and make sure I had all the cases correctly. Because since you're not describing the how, Prologue is just doing a search of the constraint space. It sometimes does things that you wouldn't think about it doing because it's just following the rules you gave it. So on to our last programming language. We're gonna do our programming paradigm. We're gonna do procedural and because I like herding brains we're gonna do it in assembly. So assembly is old school programming. Actually, I was talking to some folks at RubyConf about this and they described assembly as a memory shell game and yes, yes, assembly is in fact a memory shell game. There's a limited vocabulary slash number of functions, standard lib. I'm gonna be using the assembly from the book Hand to Tetris which I think is the elements of computing systems or the fundamentals of computing systems. Lots of assemblies exist. I'm using this one because it looks the most like algal languages which is what we're most familiar with. If you know assemblies you're gonna say that's not assembly. Yes, I understand it is not a traditional assembly but it's easy to understand and it still has all of the joys and love and problems of an assembly. So syntax, I'm working with registers. The arithmetic logic unit I'm using has two registers, A and D. D is the data register, it just stores data and circling back, car and cutter from the racket section. Car stands for the contents of the A register and cutter stands for the contents of the D register which is why they have those really strange names. So the A register is multi-purpose. It can store data like the D register but it can also store memory address. In that case it's the accesses, locations and memory. To make this slightly easier for us we're gonna use M to represent, we're gonna use M to represent the A register when we're using it to access memory. Follow? Okay. So I can do some basic computations. I have A plus D. I can do D minus A, A minus D. I can do A or D increment plus one. I can do a decrement. I have not and and or bitwise operators and I have negation. And then I have increment by one and I actually have decrement as well by one. Just a note, I don't have multiplication, division, exponentiation, any of those things that we just assume that we have mod. I have addition, subtraction, decrement, increment and decrement and some bitwise stuff. And yet I can still do really cool things. This assembly allows for assignment and it looks like normal assignment. We can assign to any of the registers or to memory and we can do that in different ways. We can assign when we're also using the variable. So I can say D equals the result of D minus A and that's just fine. And I can also assign to multiple locations at once which is super weird and super handy when you're doing crazy assembly things. I can load an integer into memory with this syntax. So this will load 100 into the A register, not into memory, into the A register. And I can use this syntax to load in the line that the program counter needs to move to for this particular label in the code. And this lets me do jumps which are the only form of control flow I have. So go to lives again. And I have a limited number of jumps. The format for jumps in this language is you have a value, a semicolon and then a jump type. All the jump types are with respect to zero. So JGT is jump if the value is greater than zero. In this case, I'll be checking to see if the value in the D register is greater than zero. I have jump equal to. This is gonna always jump and I use this for unconditional loops, similar to our wiles. I have jump greater than zero, jump less than zero, jump greater than or equal to zero. And here are some basic examples, add. I added some registers because it helped me understand what was going on better. So I load the constant two into the A register. Then I put the value in the A register into the D register. And then I load the constant three into the A register. And then I put the value of D plus A back into the D register. And then I load the constant zero into the A register and store value in D in the memory location referred to by the value it's in the A register, which is zero. Got it? Here's summation, lots of code here but we'll do it piece by piece. So I load the value zero into the A register. I store the value that's in the A register into the memory location that I'm referring to with the address in the A register, which ends up storing a zero into memory location zero. Cause you know, let's do two things at once with the value. I then load the constant five into the A register, assign that to the D register, and then load the constant one into the A register and then assign the value that's in memory look, that's in D to the memory location referred to by the address in the A register. What I'm gonna be doing this example is summing up the numbers one through five. I declare a loop, this is a label that I will come back to, then I load the value one into the A register, assign the value it's in memory location one to the D register, load the constant zero into the A register and assign the value of memory plus D into memory location zero. So we now end up with zero in the A register and fives everywhere else. Then I load a constant one into the A register and I decrement the value that's in memory location one. So now D and M are both equal to four. And then I have a label end and I'm going to jump if the value of my D register is less than or equal to zero. Otherwise, I'm gonna load up the, I'm gonna jump to the end. Otherwise I'm gonna load up my loop label from earlier and I'm gonna jump unconditionally back to the top. So now I'm back at the top where my loop label is. I'm going to load the value one into the A register. I'm going to copy the value in memory one into D. So now D has four. I'm gonna load the constant zero into the A register. And then I'm going to increase the value that is in memory location zero by the amount in D, which is gonna make it nine. And then I do the decrement again and then I loop back to the top and I add three and so and so and so. And then eventually I will get the sum of five to one. Awesome. So it's strengths. Yeah. I don't have any problems that assembly currently solves for me. I've written the assembler for this particular assembly and then wrote the bytecode that creates the assembly that the assembler reads and then I wrote the high level language that creates the bytecode that creates the assembly that the assembler reads and turns into machine instructions. But I did that because I wanted to know how my wizard box worked. Procedural style though can be really useful. It's simple. For us, most of our first programs were procedural. Hello world is very procedural. Most scripting is procedural. Do a thing, then do this other thing and then do this final thing and then clean up after yourself. And procedural style is really easy to write. We think about the world and sets of instructions. It's very easy for us to explain things as a list of things to do in a specific order. So here's making change in assembly. I am doing this the stupid way. There are better ways to do this. We can talk about that after my talk if you're interested. And this makes the change calculates the number of coins you need to give out and what coins you need to give out to make change for 67 cents. So the first memory location holds the amount to make. Memories one through four hold my coin denominations. Memory one is 25 for quarters. Memory two is 10 for dimes. Memory three is five for nickels. Memory four is one for pennies. Memories five through eight hold the number of each coin to use. Memory five is the number of quarters and so on. My assembly doesn't actually let me refer to memories by number that way, but it does let me refer to them as registers. So that's what you'll actually see in the code. So this bit here loads a constant 67, the amount we wanna make into a, then moves that to d, then loads the address of register zero and puts the amount in d into that location. So now we got the amount we wanna make in memory location zero. This loads in the values 25, 10, five and one into the appropriate memory locations. And this is the actual code and I'm not gonna do the magical table of registers here, but I'll walk you through it. So I load the location of my first memory location. I then assigned to d whatever value is there. That's the amount I still need to make. I then load up the value of memory location one and I subtract the value of memory location one from the amount I need to make and store that back into register d or into register d. Now I load up the label for my dimes code, which is the next thing I'm gonna go to. So if d is less than zero, which means that the amount I was trying to make was less than the value of one quarter, I don't need any quarters. So I'm just gonna jump to dimes and start trying to figure out how many dimes I need. But if it's greater than zero, I'm gonna load up my memory location zero, store the amount I have left after I subtract out one quarter's worth into that location. And then I'm gonna store up the location of where I'm keeping track of how many quarters I need. I'm gonna increment that by one. Then I'm gonna load up the address for my quarters loop and go back to the top and see if I can put any more quarters in. Awesome, huh? And then I do the same thing for dimes, nickels and pennies and eventually you end up getting the right answer. So learn more. I covered a lot of material in this talk and it didn't go into any depth on any of it. I really encourage you if you're interested by any of this to go out and learn more and seek more. If you want more resources on functional stuff, there's a talk parenthetically speaking by Jim Wyrick from Golden Gate Ruby Conference in 2010. It's on Comfreaks and it is really, really good. It got me to actually go back and work through the entirety of the structure and interpretation of computer programs with a bunch of friends. There's also functional principles for Odevelopment by Jessica Kerr from Ruby Midwest in 2013. And why not? The Adventures in Functional Programming which was a keynote given by Jim at RubyConf 2012 in Denver. And I like functional programming and I've followed up until about the halfway point and then I got lost. So I've gone back and watched the video a couple times because when you watch the video you can stop and think and like, okay, what is Jim showing me there? But he eventually builds up the Y Combinator in Ruby and it's awesome. If you're more of a books person, The Little Schemer, The Reason Schemer and The Season Schemer are fantastic. They're some of my favorite computer books because they're written in static dialogue because why not? They also use food as all the examples and they're pretty easy to work through. I've given them to newbies to code and they've gotten through just fine. And then there's the classic structure and interpretation computer programs, the wizard book. It's only got five chapters. How bad can it be? It's really intense. It is all you need to know about computer science. You end up building an interpreter. You also end up building a constraint solving system in Scheme and it's fantastic. So you like logic programming. I gave a talk at Cascadia Ruby 2012 called The Taste of Prologue, which just covers prologue and tries to use magical color coding and animation to make it make slightly more sense. You can go watch it on Confreaks. My favorite prologue books, there's the Art of Prologue and there's Prologue Programming for Artificial Intelligence. But the one I like the best is Clause in Effect, Prologue Programming for the Working Programmer. We are working programmers. This is our book. The reason I like this is it has exercises because it's really easy when you're reading an art book to like, oh yeah, it totally makes sense, uh-huh, uh-huh. And then you realize that you haven't actually retained the stuff in a way that you can use it. So having exercises means you have to sit and try to work through stuff and then look and see if you got it right. Procedural code. The book I mentioned that that assembly came from is The Elements of Computing Systems, building a modern computer from first principles. Oh my gosh, I love this book. You start by, you start with an AND gate. You build the polylogic gates and then you build up memory and then you build up an ALU and then you build up an assembly and a machine code that works with that ALU and then you build the assembler and then you build a byte code that generates that assembly, that generates the machine code that uses the ALU that you built of, the NAND gates and the other logic gates that you build up. Eventually you end up writing a language called Jack which kinda looks like a really stripped down version of Java and then you can write Tetris and run it on your simulated circuits that you made. It's awesome. It's really, really well done. There's actually a course error course for it. I worked through it before there was a course error course but if you don't know how your wizard box works, I highly recommend it. I managed to get through my CS degree only vaguely understanding architectures and operating systems and this really helped a lot and it also helped with PLs for programming languages. So I did a bunch of programming languages. Y'all, if anyone can probably, oh yeah, seven languages, seven weeks. Yeah, it's a book. There's good things, bad things about it. I'm not 100% fond of how they did prolog and I don't think it focuses as much on the similarities because you don't, not implementing the same thing in all the languages makes it very hard for you to see what languages are good and not good at. Someone else turned me on to the exercising, exercise and programming style, which is like 50 styles slash paradigms. I'll implement it in Python, I'll solve it in the same problem and it's awesome. So I highly recommend you try that. I'm still working through it in Ruby. It's Python's fine but I like Ruby. So I'm supposed to do a thoughtful closing right now. Yeah. Hi, polyglots are awesome. The big thing I want folks to take away from this talk is that knowing lots of languages, having these concepts abstracted in your head is good. And if you are helping folks become better programmers or if you're trying to become a better programmer yourself, get out of your comfort zone. Don't just use high level object oriented languages all the time. Having an appreciation for the other ways of solving problems can help you pick the right tool for the job. I will point out that the making change solution in prolog was actually the shortest solution there. If I was gonna solve something logic based, I would definitely use prolog. If I was gonna solve something where recursion seemed like the right solution, I'd probably actually fall back to racket. I wouldn't go to Ruby. Eventually I might do some IoT stuff where I want to use assembly but I use procedural style all the time. So knowing your tools well and knowing what tools are good for particular jobs will make you a better programmer. It will make your code better, faster and easier to maintain. And also, get out of your comfort zone. Don't just let yourself become stale. There's gonna be new languages all the time. My current language of the year that I'm gonna try to learn is Elixir because someone told me it's both functional and pattern matching and I was like, I'm there. I don't know what I'm gonna use it for yet but it seems super cool. So it might be the next big thing. I know a bunch of folks who got really interested in Go a couple years ago and now Go is the thing. I don't have problems with Go Solves but a lot of people seem to. So learn new languages, get better at stuff. I have stickers of many, many dinosaurs in my little pouch over there. I wanna say thank you and I think I have time for one question. Questions? Yes. Oh, I was gonna tell you guys my prologue joke. How many prologue programmers does it take to change a light bulb? No, you can also do yes but I like the no version better. One more question, you have one right there? That was my question. Yeah, prologue's actually a full language. It's surprising how little you need to be Turing complete. Someone has proved that you can build stuff in Minecraft that's Turing complete. So Turing completeness is interesting but not sufficient to be usable in my experience. Well, thank you all. I'm very glad Dev's working here.