 Well, welcome. I'm Chuz. This is how you pronounce my name. For those of you who can read phonetics, I can't. And this is me, but with some hair. I don't have any more. I work at Codegram. We organize full stack fast, Barucho, FutureJS, do some other cool stuff. But you're here to hear about abstraction. Abstraction is a loaded term. It's controversial. That's why I picked it. I love abstraction. And you've probably heard many times, this code is too abstract. Or even, maybe you've said it as well. However, I want to make the case that when judging abstraction, we're incredibly biased. Look at these two pictures. What are they? A machine would have a bit of a problem. I mean, maybe not today's machines, but my programs. I couldn't possibly write a program that tells me what there is in these pictures. But you already know. It's both just docs. Although they're seen from different perspectives. They are different breeds, even similar color. But one has a color, and the other one not. I don't know. It's different. But you know that it's docs. Your brain just sees this. And then you know a lot of stuff about docs. So you just pull that out of your semantic knowledge in your brain about docs. So you know that docs go for walks. And you know how to feed a dog. So that's kind of useful. You've never seen these two docs before, but you know they are docs. Now, my favorite writer is Jorge Luis Borges, an Argentinian writer, really amazing writer. Just go and buy all of his books. And he wrote a story called Funes de Memorias. Also, as it turns out, one of my favorite stories. And in this story, he talks about Funes, a young man who fell off a horse. And from that moment on, his memory became perfect. He could no longer forget anything. So everything he sensed, it was permanently there in his brain. And of course, he became a bit of an eccentric and started taking on bizarre projects. Like, he would try and reconstruct, write down, an entire day of his life with full detail. And of course, that would take him at least one entire day. And then he also, he got a bit weirder and started thinking. He told Borges, who is a character in that story as well, look, I started working in this numerical system. I invented a numerical system. And Borges was like, really? Just tell me about it. What is it? And Funes said, well, I assigned to every number a name. So the number seven is chair. And the number 200,531 is dog, and so on. And he would just write down all these names for every number. And Borges said, but isn't that kind of the opposite of a numerical system? Like, you cannot reason about numbers this way. If every single number has a name. But Funes wasn't interested in his arguments. He just kept on just designing the system. He really liked it. Borges went on and said, look, John Locke, the philosopher, once envisioned an impossible idiom, a language where every single thing had its own name, a unique name. So every instance of every branch of every tree had a unique name. Of course he discarded the idea because he thought, this is a stupid idea. You cannot think about anything if everything has its own unique name. You cannot even talk about anything with anyone because you cannot communicate a generic concept to some other person who has never seen it. But Funes, he was bored by this system. He thought this system was too general. Because to Funes, not only everything deserves its own name, but every, if he saw a dog at 3 PM from the side, that dog doesn't deserve the same name from the same dog seen from the front one minute later. It's a different thing. It looks completely different. And you sense it in a completely different way. So it needs its own name. So Funes couldn't abstract over time. We abstract over time all the time. We have this notion of identity. We look at a thing, and a second later, we know that it's the same thing, or we think it's the same thing, and we talk about it as if it was the same thing. But to Funes, that's just losing detail. It's funny because, of course, you will think that Funes seems like quite a brilliant individual, like a weird guy, but quite brilliant. But Borges made the point that he suspected Funes wasn't really capable of thinking. He said, to think is to forget differences, to generalize, to abstract. And Funes could not do that, wasn't interested at all in generalizing. So of course, we've talked about dogs, and that's kind of unfair. Because even if two dogs are dogs, they are different. And they are different in an infinity of ways. So let's go to a more basic domain, for example, addition. Addition is something we can grasp much better than what a dog is. We know how to add numbers. We've been doing it since forever. And we as programmers have the special power of adding strings as well. Because to us, it's basically the same thing. You just concatenate two strings. We could go further and say we can also add lists together. So we could say that if you take one thing and you add it to another thing, you get another thing back of the same kind. You don't get the same thing, but you get something of the same kind. Another property of addition is associativity. So it doesn't matter where we put the parentheses. It always gives the same result. Same applies for strings, and same applies for lists. So we're seeing a pattern here. For anything you take, no matter the parentheses where they are, it always gives the same result. Now addition gets more interesting with a special element that it's only been around for a few hundred years. And that's 0. It's a magical number. If you add 1 to 0, you get 1. It's as if it didn't do anything. We also have the same for strings. It's the empty string and the same for lists. So you're seeing a pattern here. If you take a thing and you add it to a thing that's special, that we call it the neutral thing, you get a thing back of the same kind. Actually, in this instance, you get the same thing back. So we have these two properties that we've seen of addition, no matter if it's about integers or strings or lists. Associativity and a neutral element. That's interesting to know, but how useful is it? Well, one instance where it is useful if it's just knowing this about something, and we know that about integers, strings, and lists, you can fold over a list of things. So in this case, you fold over a list of integers, which in Ruby is reduced or inject. And because it's associative, it doesn't really matter if you fold left or fold right. That's kind of a nuance. But you can use either, and you get the number back. The same for strings. If you have a list of strings, you can fold, starting from the empty string, and the same for lists. So we can say that if we know that we have a neutral element and something that adds associatively, we can fold over a list of it, and we don't care what it is. Now, you might argue, of course, numbers, strings, lists, these are very primitive things, and it's kind of a coincidence that works this way. But of course, that's not useful in my programs, where I use complex objects and structures, and that doesn't apply to my day-to-day. But I dare you to think of a data type more opaque and weird than functions. Functions are kind of a collection of code to be run later. Can we do the same with functions? Let's see. We can add functions together. If we understand add as composing functions. So we can compose f and g and apply it to x, and it's the same as applying first g and then after the result of that. Do they add associatively? Well, as it turns out, they do. But what about the neutral element? Do we have a zero for functions? Is there a function that does nothing? Well, the identity function does nothing. It returns its argument. Fair enough. Let's see. Oh, that holds. You can compose f with the identity function and you get f back. So if everything I've said is true, you could fold over a list of functions and get the composition of all of them. So we've seen just by knowing these two things about functions, about a thing, we can fold over a list of those things and we can do much more stuff. But folding is just an example. Now, it's not only about functions, numbers, strings, and lists. You should go through your own code base at work and look for things that look like this that add associatively and have a neutral element. And you need to think abstractly to recognize this pattern. But now that you've seen it, you'll probably see a lot of things that look like that. Maybe validation errors. You can add them together. They just become a bigger error. And you have a neutral element, which maybe is the lack of errors, a success, a value that represents no errors. Think for yourself in your code bases. You'll find a lot of examples that behave like that. So because it's a bit clunky to say just associative addition and neutral element, people don't talk like that. Someone gave it a name. Monoids. Now, let's talk about things in plural. We use arrays, lists, and sets in our day-to-day all the time. But we're not interested in the nuances of each of these types. So we'll just talk about collections. Collections of things. Doesn't matter if it's an array or something else. So a collection is something that has the notion of zero or more things. And what can we do with collections? Well, in Ruby, we're pretty used to map. We map over a collection. We do something for each element. That's actually more interesting than it looks, because what if the collection is empty? We know that map doesn't do anything. It just returns an empty collection. So this is how it works. The code is pseudocode. Don't look at it. Don't take it seriously. It's pseudolispy code. But it's not even closure or anything like that. So we see that it works for a list of things and for an empty list. Now, there's a special kind of list. A list of one element, if you will, which may contain either one element or none. And in some languages, they call that optional or maybe. It's literally just a special kind of list, right? Either zero or one element, but none more than one. So if it's so similar to a list, could we map over it? If we map over it, then it just applies a function to the only element that there is. Or if there's none, then it just returns none, just like an empty list. OK, now there's something a bit different. A future. How many of you have used futures in your day to day? OK? A future encapsulates the notion of eventually something. So not now. It doesn't exist right now. But at some point in time, there will be something. Or not. Maybe there's an error. So it also encapsulates the notion of an error. Futures, you can map over as well. You're telling them apply this function to the value eventually when it exists. And if it doesn't, then just don't do it. Just give me back the error, wrapped in a future. So you're probably seeing the pattern that futures, optionals, and lists can be mapped over. And they are very different things. And mapping has different semantics. But maybe not so different. If we look at these things as boxes, just kind of boxes, containers of things. Let's call them boxes. So instead of collections, futures, optionals, just talk about boxes. If we looked at it just more abstractly as a box, what would be the semantics of map? Mapping a function over a box applies F to whatever is inside the box in the way the box sees fit. If it's a future, we'll do it later. If it's a list, we'll do it for each element. And then return the result in the same kind of box, be it a list, or a future, or an option. I cannot stress enough. It will apply it in the way it sees fit. So a future has its own way, a list has its own way, an option has its own way. However many times it wants, exactly when it wants, if at all. That's a lot of power. We just give it the function, and magic happens. You're probably thinking, that sounds an awful lot like encapsulation. I'm used to that. It's like an object. You just tell it something. Do this in whatever way you want, maybe. And of course, it's not good to reach into objects. And it's not good to reach into boxes either. If you try and get the first element of a list, and it's empty, what do you get? Nill, an error, depends on your language. That's not a good thing. If you try to unwrap an optional, and nothing is there, what do you get? Nill, or an error? That's scary. You should be scared of nil. If you try to unwrap a future, basically you need to wait until it exists, right? That blocks the thread. That's not a good thing. So you're better off telling the box, look, do this whenever you want in whichever way you want. Let the box decide. These boxes, box is kind of a stupid name, so some other people give it a smart name. Functors. But you can keep calling it boxes. It's better. Now, it's fine, but this kind of, can you just use map for everything? Can you just map over things? Sometimes our functions are not that simple. There's a kind of functions that are very hard to compose with these boxes. If you have a box of a type T, a box of integers, and then a function from T to a box of U, be it something else, this kind of shape, it's hard. You cannot use map with that. You end up with nested things. But let's get a bit down to more of a concrete thing. So if we have a collection of strings and a function from string to collection of strings, then if we keep mapping over the collection, we just get nested and nested collections of strings. And that's maybe not what we want, probably. For an example, if we start off this string and we split by comma, we get three elements. If we want to split by dot to each element, we end up with a nested collection. What's the problem with that? Well, if we wanted to keep on processing the elements of the list, we need to know the depth at which they are. And that's a knowledge that we don't want, because that doesn't compose. If we pass this to something else, it needs to know the depth of the data structure. And that's a lot of information that it doesn't need. So there's, of course, another function called Flatmap. You also have it in Ruby, which just applies the function to every element in the collection and then concatenates the result into a flattened collection. So fair enough, Flatmap does exactly what we want. Again, ignore the code and just sue the code. So we get a flattened collection. The same problem arises when we have an optional and a function that yields a further optional. It's a lot of uncertainty. From a user, you get an address. Maybe, maybe it's not there. Maybe a user doesn't have an address. And from the address, the address may have a string number or may not. So we end up, by mapping, we end up with the same nested structure that we don't want. So Flatmap also works for optionals. And that's not surprising at this point. We see that map is defined for all these kind of boxes. And Flatmap seems to work as well. We end up with a nice flatten optional. If any of the intermediate steps yields none, then we just get none. Now, with futures, that's even more common. You go and make an API call and grab some resource. And then, depends on the result of the resource, you need to call some other APIs and get more things. So if we were calling the GitHub API and we get a repo, and when it comes back, we need to get the followers of the repo. If that was a different API call, I really don't know the GitHub API. You would start off a user. You get the first repo, which is a future of repo, because it's not there yet. We get the followers with map. You get a nested future. Not what you want. With Flatmap, you get a single flatten future. So for all boxes, all kinds of boxes, Flatmap does the same like map. But then it flattens the result into a single flat box of the same kind. So whenever you see this, you have a box of T. And then these functions that go from a normal value to a box, and you need to keep composing them, Flatmap is what you want. This gives us a lot of power. If you see, map was kind of stupid in the sense that if something depended on the result of a previous competition, you couldn't do anything. But in this case, you can have functions that do something depending on the value of some other box value. And when you see this, and you want to use Flatmap, you can actually say that you're using monads. That's what monads are. These boxes that you can use Flatmap with, with these kind of functions. So as a recap, we've learned that just by knowing these two things about something, we can fold over a list of them and do many more things that are out of scope for this talk. We can use map to go from a box to the same kind of box doing something in between. We can use Flatmap when our shape is like that, when you have a nested box. So now that you've seen these and you have names for them, be it the smart names or the normal understandable names, now you're going to look at your code and you're going to see these things. And then you'll have very powerful and general ways of dealing with this, namely map and Flatmap. Just two functions to do everything. Not everything, but most of the things. So there you go on Monday to your code bases and try to look for these patterns. Because now that you've seen them and you can name them, you can think about them. I'd like to give a special thanks to Jessica Kerr, who helped me a lot with the structure of the way to approach the teaching. I know it's a hard topic to teach. So I hope hopefully you got a better insight into the world of these really powerful structures and functions. Thank you. Hey, thank you for your talk. So yeah, thinking about this kind of abstraction is really rewarding in a way because it caters to your human instinct toward abstracting things and thinking about higher level abstractions. But still, let's say sometimes it's actually hard for people who are not used to these kind of things to grasp it. And you were saying before that you think that we are heavily biased towards abstractions. Well, I assume you think that most people have problems with the structure or judge them not necessary or whatever. So what do you think is the best argument you can give for convincing people that, well, actually, it's not that hard to make the step to think in these terms and actually make good use of them? In the same way that you probably at some point someone sees the visitor pattern and they are like, what is this? And then they need to learn it. And then it's natural to them and they see it everywhere. I think it's no different from these kind of abstractions, but there seems to be something different about them. They're scary, everyone is scared about them, and that's only because I think people suck at teaching them, myself included. But there seems to be even a hidden interest to never teach that to anyone and just use opaque words so that people never actually learn these powerful constructs. So I think it's just kind of removing all the mystery about that and just teaching them is just normal things and not making them scary. But that's easier said than done, of course. But I think a lot of people are trying to do that, and I think it's good. We've done a lot of progress. Great. Another round of applause for Chuse. That was a great talk. Thank you.