Heloisa Carbone - The advantages of functional programming with Clojure
Video Transcription
Hello, everyone. I think I can start now. I am Eloisa Carbone. I'm from Sao Paulo Brazil and I'm also a software engineering at New Bank, uh which is a fintech, a Brazilian thinktech that uses closure as its first language.And today I brought this amazing topic that has been part of my life for the past two years to talk a little bit. So let's discover uh a little bit about the advantage of functional programming with closure. And to start in introducing this topic, I would like to share uh a little remark about paradigms with you because you truly understand what functional programming is. It is better in this way. What are the programming paradigms that we have today? Right. The paradigms are different approach that we create to solve a problem. So sometimes we have like different implementation problems that we want to solve in different ways. And sometimes we choose different paradigms to that. And we have many paradigms. So we have two big groups which are the imperative paradigms and then declarative paradigms. And the famous paradigms that we are used to are inside the group of the imperative paradigms which are a paradigm, object oriented paradigm, parallel paradigm and many others. But in the other hand, we have this group of the clarity paradigms in which you have only three types of paradigms, which are the logic, the functional and the database. And what is the difference between those two groups? Right.
Uh I think that we can to understand clearly what, what this mean is like imperative programming is like how you do something and the clarity programming is more like what you do the imperative program and it's more used among the industry among the diversity course, uh everyone might have like some contact with those paradigms uh more easily.
So you have like access in any place that you want. But on the clarity paradigms, this is something that you should probably seek to uh to find it. It's not so common to have it around. And the functional programming is aside this declarative, but to truly exemplify how those in narrative versus the clarity programming works, we can think about the real situation. So imagine that you are going to your friend's house and you ask her address and then if she answer you in the clarity mode, she would say, oh I live at XYV Street and that's it. She just gave you an address. Uh and you like do uh in any way that you want to get there. But in imperative mo she would say to you like that, oh leave your house and then get the first three for four blocks and turn right on mcdonald's and write for three more blocks and then my house is going to be on left. So she gave you step by step, what should you do to get there? Not only give you uh a destiny. And this is not like all the difference that those two paradigms that those two groups have.
But this is like a good example of how they work, uh how the line of thought work. And we have like many paradigms as I mentioned and we have an evolution of them. So they were created and changed over time. And here I brought the functional programming paradigm uh and the object oriented paradigm, which is the famous one nowadays, I think it's the most famous if I have to say and if we uh uh object oriented is like younger than the functional programming. And sometimes we not even have heard about the functional programming, we just like started to hear about it in recent years. And it's like it was created in the fee. So it's uh much older and has been used mostly at the academy. And here I brought as well the comparison between the two groups of the native and the declarative, the imperative was created first. What makes sense? Because if we imagine that the machine language were created in the beginning and they were like step by step rules of how to run the, the machine. Uh It makes totally sense that that to be the start of the imperative programming, the the declarative programming was created when functional programming started to be. And as I mentioned, the paradigms are created to solve problems.
So we create those approach to try to solve something that was generated by other things. And sometimes we have like some problems that are created by the imperative programming paradigms that the function of programming tries to solve. So what are those problems that we have?
So the first thing in the imperative paradigm is that it's difficult to create relevant tests that guarantee reliability. So it's really difficult to test sometimes and also to debug because we have like some problems that happen that we are not able to reproduce and try to identify it.
Uh mostly because we have many mutable variables. So sometimes we declare a variable at one place of the code and the other, we change the same value to other uh valid. And this is something that we don't have like much control and we even use sometimes those mutable variables as conditions to keep our code running. So sometimes we open a connection to a database or to a socket and we rely on this connection to keep our code running. And this is not something that we can like come true. So if this like close the connection and we lose total control and some side effects happen, so we have like many things that go outside of our code. So throwing a horse would be a side effect in this case. And it's really difficult to predict and we want to avoid all those problems. We want to, we want to try to solve it with functional programming. So functional programming has many guidelines and concepts of implementation that help us to solve those outrageous problems. And we have some concepts here that we try to seek with functional programming. And the first thing that we want with functional programming is to have immutability.
So all data should be unchangeable. I I cannot create a variable uh here and modify it lately. So I am only going to be able to read this variable, but I'm not going to be able to modify it. And this is like the main group of functional programming, all the uh programming language that apply functional programming, try to follow that and the new ability as well is a safe characteristic to prevent concurrence problems. So it's something that is really useful for us.
And not only that, but as the name states functional programming, uh we want to have our code based on function. So we want to have functions first. So we need to start thinking about uh functions that can help us and there are a much easier to task. So we want to have like a small and direct functions that we are able to task. So we want to have pure functions and pure functions are functions that we are able to predict what, what they are going to resume. So for example, if I have an addition, always it's going to be one plus two, it will always going to result in a three. So I'm able to predict that. So that's OK. That's what I want. And with functional programming, uh we want to have function composition as well. So if we need, we want to create as many functions as we can and we can, we need to be able to use functions inside functions. So for example, if I have a subtraction here, my subtraction could be a composition of other additional functions. Um uh Don't be scared. Those are some examples of closure I will explain for you later. But just to exemplify those ideas of functional programming, I'm bringing them now.
And other thing that functional program seeks is recursion overlook so to iterate data and also we prefer expressions overstates because expressions can be predicted, we are able to predict what what they are going to sute. And if you run as many times as you can, they are always going to result in the same value. Uh What is different from the statements which are functions that do not return any value and only generate side effects. And what we try to avoid the most in functional programming are shared states which are the global variables that we use over time. So we don't want to rely on a connection, for example, that was created and open at some place on the cold. Uh So we try to avoid those kind of things and also we try to avoid the side effects. And I mentioned this word a lot, but I didn't explain exact what the side effects are. Right side effects are everything that go outside your function. So for example, a been through is a side effect. Uh a print to my terminal, it's a side effect, a connection to a database and a and many other things that go outside your functions are side effects. I cannot say we do not use side effects in any situation. Of course, sometimes we need to connect to a database, we need to update things and everything. So we try to do it in a concise way.
So we create small functions that we only do those things that we only send those side effects. So we have like control over the whole thing. And I know that all these concepts are quite different than what we are used to. And we need, we need to change our mindset to truly understand functional programming and to be starting to think of how to transform data to achieve what is needed instead of change the variable over time. So transformation is the key to a well written functional programming code.
And functional programming has many programming language that implement it and that are able to accept or even were viewed with the functional programming mind. And here I brought some examples, for example, Java, which is an object oriented programming language. And I think it's the most used nowadays by all the industry and in the courses and universities and this language. After the release of Java eight, it also accepts functional programming as the LAMBDA function. So we are able to program in both approach at the same time. And also we have script which is a mood paradigm programming language and also accepts functional programming pretty well. So what I want to say to you at at that is that programming paradigms is not like opposites. They are not. If you choose to use one, you cannot use the other. No, you can use them alongside each other and take the best of them for your needs. And with that said, we had like some other programming language that were built with the idea of functional programming mind. So all their concept or all their structure is based on functional programming. And I brought three examples here, which is the ho language, which is a general proposed language and it's highly used by Facebook. And also this, which is the first functional programming language created.
And this is the language that was created in the fifth. And it has an interesting history that it was a student that created a student of MIT and he was doing a research about artificial intelligence projects and he needed uh some uh programming language that could be able to process lists of data that he didn't have at the time.
So he decided to create lists to do this for him. And all the idea that he used all the mathematical things he tried to implement on this function on this programming language. And he created uh with that and it was like really acceptable for everyone, mostly in the academy and many other programming language were created based on the dialect of Liski. And Closure is one of those programming language that were created with the dialect of Li. And now that I mentioned Closure labs uh that deep in the programming language which that I brought today. And to start, I would like to tell you a little bit about its history. So closure was created in 2005, but it was only released in 2007. And it was created to be designed as a general proposed language, a practical functional functional language that would be suitable for use by professionals, whatever its host language was Java, for example, and Rich Hickey was the creator. And a fun fact is that he created this language in his sabbatical period of his life as a personal project that could revolutionize the tech industry, not only the academy. So he built closure to be a functional programming language that could be used in huge services and huge industry. And he built it on the top of the J PM, which is the Java virtual machine.
And this allows and gives the benefits of functional programming on whatever platform you like. Because we have like access to the J PM for uh from our computers, from our cell phones and everything. So it's a simple way of programming doing as this. And as we know, the JVM is also uh as a platform is also became a stable base for building large software systems on top of it. So it was like easier and accessible for anyone that I wanted to try. And not only that but closure is also an open source language and has Interpol ability with all the libraries and frameworks of Java. And as I mentioned before, has the Lisp dialect and what it means to have the Lisp dialect I mentioned at the beginning that Lisp was created to be uh a a language that could process lists of data. So imagine that all the structure of this dialect is based on lists presented by parenthesis. So this is like an interesting characteristic of closure and all those these dialect language which is they are based on parenthesis. So everything is about parenthesis. I even brought this comic strip that says these are your father's parenthesis, elegant weapons for a more civilized age. So everything is about parenthesis. I know that is a scary when you look at that, but don't worry, it's quite simple.
And if you understand what those parentheses does in a simple way, you're going to see that everything that comes after. It is quite easy. And here, uh let's discover how this parenthesis works. So this is like the main and most important thing in closure, those parentheses with a functioning and argument. This is our declaration that we will uh be uh followed in all the code and everything and what they represent, right? Those parentheses are lists, but they are also in vocation. So imagine that when you have those parentheses, they are calling a function or they are trying to apply something on those arguments. And this function name could be a symbol or a, a symbol would be similar to the addition that I showed earlier. But the string would be like the declaration of a function around the codes that you invoke here. And my arguments are numbers, strings, lists other functions in any number that we need. So we, we can decide uh to have like as many arguments as is necessary. And here I have like some examples that I showed early, the addition. So here I can see that I have my parenthesis, then I have my addition symbol and then I have one and two being my arguments. And I know that this parentheses are invoking the application of these arguments to my symbol plus. So one plus two is equals three.
And the other example of the function composition, we can see that we have other functions as arguments. So I have as well my indication of the function, my plus symbol and then I have a function which is a subtraction with the same idea of I have my minus symbol of two and one in the arguments. And then I have other addition and all this results in a three as well. So don't worry, I know that this is different but it's quite similar and it will be like that too the end. So everything that you see in closure will have this structure and closure has a strong data structure. So those are some things that we have. So we apply immun ability all the time. This is like the first rule that I mentioned about functional programming and we use it like all the time. So we do not like modify our variables all the time that we create or exit a variable, we are actually creating well. So our variables are only able to be readable. They are not able to be modified and we support a quality semantic. So we are able to compare variables to compare values. And also we have lists as I mentioned.
So we have collections and they can be manipulated and iterated over time. Closure relies on types and has a huge number of data types. So similar to Java, we have string, we have numbers, we have lists, we have symbols which is uh not so used in other programming language. But in closure, it is highly used and is represented by two dots and a string name. For example, here I have two dots. Hey, I am a symbol. This is quite used by to be a key value in a map and also to be an in room. And so this is highly used since day one and also closure has dynamic typing. So it does not verify types during compilation, It only does at one time. And it's also a home iconic language. I know that is a weird world. And in the past, I hadn't heard it before. But this means that all the codes that we have is actually data. So everything that you implement in closure is data. So we have we have this home iconic city implemented. And with all that said, uh I came to this topic of macros. Macros are something that we have enclosure that is stronger than in the other language. Uh So this is enclosure is a simple thing that we use all the time. It's not something that you need to be like a senior programmer to start using as it is in other language. So this helps us to modify the code and extend to our needs.
So we do as we want. So we create things that will help us to to achieve something. And this is because our code is all data. So this home iconic allows us to you have that and closure has many building functionality that are macros actually and they are based on building functionalities in not all. So here I have an example, I have the one condition that we have in closure. This condition is highly used. So the representation of this is like when something happens, I'm going to do this and this is a macro that a red comes with closure. And we, if we see the implementation of it, it's actually a need with a do. And we have many other macros. I even introduced this topic because I want to talk with you about an interesting and really useful macro that we have that helps us to have the transformation. I I brought this word before and I said to you that this is the key to a well written programming language called with functional programming mind. And with, with this idea of macros, we have a macro that helps us to do that and to show you this and some other things about closure.
I brought a case that that will help us to truly identify what's happening and why they are used and why they should be used. So here I have uh a variable. So this is how I declare a variable enclosure. That's the name of my variable, which is case ST and my array of people. So here we can see that each people has a name which is a symbol with a string value and an H which is also a symbol with a number of value. And let's imagine that this is all stored in a database and we want to do some stuff with this. So the first thing that we want to do is to add a new attributes, profession to each element of this list of people. And after that, we want to update this new list to my database. And finally, I want to be able to filter everyone that is older than 21. So if I put it in words or in programming style, I would do something like that. So I would have my case, then I would add for fashion, then I would update people with profession. And finally, I would future people over 21. And this is actually something in closure. This single arrow is a Macro. It's a thread in macro enclosure that allows us to do it in a simple way of reading what you need to do exactly.
So in thread, we have two types, the thread first and the thread, the thread first is this one that I showed you if the single arrow and the thread last is this other with the double arrow? And what those two threading macros will retrieve to us. So imagine that those things are being applied to our case start. And after I run all of that, I will have this result, I will have uh only people that are older than 21 with their new attribute profession uh being displayed. But let's truly understand what they are doing because and it's going to be easier to understand. So in thread first, uh I put my single arrow as being the first parameter of my parenthesis as you can see. So it's the symbol or the function that's going to be applied. And then my second parameter is the case to which could be uh a string, a number. But here is my list, my list of people and this is passed as first parameter of my next function. And all those uh functions that follow add profession to list eight people with profession, future people over 21 are functions that are declared around the code and they only have one argument uh to receive something. And here the the first a profession to list is receiving a list.
So I am receiving the cases as my first parameter here. And we know that this function retrieves another list that is passed to the next function as first parameter as well and the same to the last one. So this is what for thread versus it pass the argument the value, the variable as first parameter to next function in in sequence and the thread last does the same but passing this variable as last parameter, not as first. So here I have in the sequence, a map in my thread last. And this map to for each, if you can compare with other language. So it's going to iterate over my list and it's going to apply a function which is the a function to each element of this array. And after that, it will retrieve other lists. So this is a be functionality of closure. I know that many other programming language has this implementation map. But this is the idea. And as I showed you in the thread first, the eight people with profession only have one argument. So this argument could be the first or the last. So it's going to receive the same list here. And finally, it's going to retrieve other lists that's going to be passed to this future. And the future is similar to the map.
So it's going to iterate over each element of this list and it's going to apply and predicate it. So it's going to check if this uh person that has been analyzed is older than 21. And here we see that we have like a different implementation of a function. So this is how we create an anonymous function. So instead of creating a declaration outside my my code here, I decided to create an anonymous function that would call other function that was already created. So this declaration of sharp with parenthesis is an anonymous function.
So it is an invocation and, and inside it, I have this over 21 which is a function that is declared in my code and it only receives one element which is a number. And here we have other interesting invocation other interesting parenthesis with a symbol and a percentage. The symbol is the two dot that we, we saw that something that we have in our case test and this percentage represents each element that's going to iterate it. So here I am saying that these elements that I am in it is only going to retrieve to me the evaluate of age. So I'm only passing through this over 21 the evaluate 18. And this is how I check this anonymous function. This is how it works. So apart from the threading macros, this is something enclosure really useful that you can use like uh in many situations. And now that we understand what those macros are doing, let's see the implementation of those functions that they are calling. So I'm going to start with the thread last functions because they are pure functions. And here uh I have the a profession which is the one that we use on map. So DFN is how I declare a function enclosure. And then I have the name of my function, which is the a profession, a number of arguments that I have. So here I receive person as my argument. And if we check in our case that it would be uh one of the elements of the list.
So for example, named Anna with age 22. And in this implementation, I declare a variable inside my function. And this las profession, software engineering, it's how I declare a variable inside a function. Not like outside the daf that I showed you early. It's more like a global thing.
And so here I'm declaring a profession with the symbol software engineering. And in the last line, I'm assorting this ball to my person. So I'm adding this attribute to my person. So I was having something like that. So I have my name age and the professional software engineering.
And in closure, we do not need to put any return statement to say that we are returning something. The last thing that we you do in a function, it's what's going to be retrieved. So here we, we are retrieving this new uh map with this new attribute profession. And after that, we had to update people with profession, which is the function that we store our new list database. I didn't put it here because it's not necessary. I just wanted to show something really interesting here, which is this exclamation mark and exclamation mark represents that this function we generate side effects. So as updating something, a database is a side effect. I declare as a code convention enclosure that this function is doing that.
So here I just return the same list, but it's actually a new list of people. But that's what this function do. And finally, the over 21 function, the function that's going to check if the age that has been passed is uh greater than 21. And here we have a question mark and the question mark as well, the exclamation mark represents that a boolean will be retrieved. So it has a meaning. It is also a con coven enclosure and it states for us that it only retrieves a billion. And now we are able to truly understand what this thread last is doing. So I have my case study and I'm going to map each element of my list to add profession. And then I'm going to date people with profession. And finally I'm going to future people that are older than 21 and the thread first functions are a bit different. Uh So here I have the a profession to list which has receives all the lists, all the, the people. So it receives people and applies the same math that I did in the thread last. So map a profession. So it uses the other function to each people of this list. So what I it was to put all implementations in a new function and we also have the future people over 21 which it does exactly the same of the future in the previous one. So here I'm receiving all the list of people and I'm doing this future.
So it's going to iterate over each one of these people and, and we all find who is older than 21 as well. So now we are able to understand what the thread first did here. So I receive with my case, then I add profession to this, then I update people with profession and finally, I future people over 21. So this is the case that I brought. I think this is a better way to exemplify and show you some stuff with closure because I know that it is really difficult to understand what, what everything does. And sometimes with an example, it's much easier what they, what they are actually doing. So I think a case that is a better approach to do that. And with all that said, I want to say that closure, the special programming language and it has an accelerated learning curve. So I I can say by experience that everyone that starts using code uh closure and starts coding enclosure has a fast grow in knowledge. So in a week, you're able to create something from, from zero and has like a good experience. So it is a good Gramming language to start if you want to learn uh a function of your language.
And it's all mostly because it has a simple grammar, it might, might look a bit weird because we have like so many parentheses and we are not used to that, but it's all about parenthesis. And if you understand clearly well about the invocations, name of the function or symbol and arguments, you're able to predict everything that's going to be done in a in a, in a code. So you are able to read and understand what it's being done. So it's easier. So it has really a simple grammar and not only that, but closure has a great community which is really collaborative and helpful. And you are able like to connect with them and give feedbacks and try to share ideas of things that could be implemented and they are all well uh acceptable and they want to have those approach. Closure is not like a language that has many stack overflow questions answered. So it's difficult to find any specific doubt but the documentation is really good. So because in the documentation, you have the explanations of course, but you have many examples because the community helps to do it. It, it puts examples of how you can implement something of how can you use something. So you have like many examples that help you to understand and, and start coding.
And if I could like give uh uh a thing that where to start in closure, I would recommend a book that is The Closure For the Brave and True, which is uh super fantastic book. It's truly didactic and has like an awesome way of teaching. Uh It's like a closure fairy tale actually. And it's really useful for you like to start understanding what everything does. So uh it's pretty good if I could recommend I would say start reading this book because it's going to be a good uh reading and also it will teach you a lot. And with all that said about closure, I want to say for you to make closure be ever in your favor and functional programming in your life, I hope you had enjoyed and learned a little bit. Uh You can find me on social media by Eloisa Carbone. And if you have doubts, concerns feedbacks just you can send to me and I will be delighted to answer to you. And, and now I would like to open for a few questions if you have, but because we still have a few minutes, so I would check if you have some questions in the chat and then I can answer you and thank you very much.
Mhm uh uh We have like a question that says when Macro seems very similar to imperative programming. Yes, it is something I wanted to show to you mostly because this thread in Macro is something that brings us to this idea that we are used to about programming. So this idea of putting line to line of thought because in a normal way of programming, if we do not use threading that, that I showed you, we, we would have like many uh parentheses inside parentheses. So imagine that instead of I have like that line of thought, I would have my future first and then inside my future, I would have the, the call to the database and inside the call of the database. I would have my map. So it would be really confusing because this is the way of thinking in closure and in functional programming. But this threading macro allows us to make it easier and try to put it in a easier way for us to read the code. It's even better for us to try to identify problems and check things. Because sometimes if we do not use the, the threading macros, it's really, really difficult to put it like in words, what's happening because you lose control of the parenthesis. They are quite amazing, but they sometimes you don't know where the the parentheses close. Uh We even use some uh some tools that help us to identify the parenthesis that put all the parentheses in color, colorful mode because then you're able to see where the parentheses close.
But the thread in macros allows us to do it in more imperative mode. So it's better. Oh, thank you. Someone said that like in my examples and analys, thank you very much. Uh I tried to put like in a more real situation way because it's easier to understand. I, I know that this topic is a bit confusing and a bit different than what we are used. So I think that's a great way of doing. So. Thank you very much. I think we don't have like more questions, but I'm open. If you have like questions in the future, just contact me that I would be delighted to answer you and thank you very much for being here today with me. Thank you.