Functional Programming in Kotlin - Venkat Subramaniam

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
alright let's get started welcome to the session on functional programming in Cartland I'm gonna talk about a little bit about functional programming and then show a few things we can do with Cartland in terms of writing functional style code and I'll also talk about what it means to be functional along the way as well if you don't have any questions or comments I'll be thrilled to hear from you let's just begin speaking even though if I may be looking at your direction I may not be paying attention to you so draw my attention and then you know speak up I'll be more than happy to listen to you so with that said let's get started well one of the things about functional style of programming is that it gives us an ability to solve problems by reducing quite a bit of complexity in code well let's talk about imperative versus decorative and then a little bit about functional style just to set the stage for what does it really mean to do this well in the imperative style of programming we we show what to do but also we tell how to do it so the entire burden of writing the code with all the details falls on our shoulders so let's look at an example really quickly I want to talk a take numbers as an example is equal to list off let's go ahead and say I have a list of numbers let's say 1 to 10 so given all these numbers list of 1 to 10 what I want to do here let's say is to total let's say total of all you know total of let's say double of all even numbers so I want to compute the total of double of all the even numbers you know how would you go about doing that with the imperative style of programming well you would typically create a variable to hold the result and that's the first smell you got to create a mutable variable to start with then you can say far and you can provide a number and then number coming from numbers if you will which is this collection of numbers you want to deal with when you are done with this of course you want to eventually print the total and we haven't really done any totaling yet so it is zero at this point but what you can then do here as you can say yes the number that is given to us is a even number so you can say mod 2 is equal to zero and if it's an even number then you can say a total plus equal to the given number times two and you can then start totaling the double of all the values in the collection so when you look at this that is quite a little bit of code to write where we have to loop through and write all that code telling how to perform the product how to perform the total as well and how to add them back to the collection all the details it's on our shoulders and that is the imperative style of programming we all have done that in in languages before cotton does not prevent you from doing it if that is the right choice for you you can still do that in Cartland the decorative style of programming is where you focus on telling what to do and not how to do it so you can simply say what you want rather than detailing the steps of how to do it so this is like talking to an adult and you are able to say get me some water and you don't have to explain to them how to get the water they know how to get it so you're calling functions that can do the work for you rather than having to spend time on low-level details if you look at the code we just wrote you had to say how to perform the total of the product you have to write the piece of code rather than just directing to say go do this for me so decorative style is where you can focus on work and not focus on the how well the nice thing about functional style of programming is that the functional style of programming gives you the ability to move a little further with those details I'm gonna save this along as we speak so I'm just gonna say Imperator right there and save it but I'm gonna talk about the decorative style what does it mean to be declarative well to understand what decorative means so imperative is where you tell what and also how well declarative on the other hand is tell Ward and not how so you are able to focus on just the word that you are a goal when it comes to doing that now what is really cool about functional style is functional style is declarative plus the use of what are called higher-order functions so this gives you a nice way to build on the concepts of functional programming with declarative and bringing in the higher-order functions so that makes the question what does it really mean a higher-order functions well I'm gonna say first of all normal functions I don't even know if it's right to call something as a normal function well non higher order functions so a normal function a regular function what does it really mean well we pass object typically to functions and we do this all the time we pass objects do functions and so these are normal functions a we create object in a function so we do this also quite often and then finally of course we return object from a function and and these are the things we normally do when it comes to programming we pass objects to functions we create objects within functions we return objects from functions as well but on the other hand when it comes to a higher-order function what it means is that you can take this idea and you can go a little further with this and that is we pass function to function we create function within function and and also we may return a function from a function and and that's what makes a function a higher-order function so a higher-order function is a function that may not just receive create or return objects it may receive create or return functions as well and and one of the cool things about doing this is in addition doing object composition we can also do functional composition now if you really think about it if I were to think about object-oriented programming I I could say that here is an example of a bottle but but from the oral point of view object-oriented programming point of view what is a bottle made up of this is what we call as aggregation so aggregation says this bottle is made up of the containers plastic it contains a nice label it also contains a and and maybe it contains liquid inside of time so so you can say there are four objects that came together to create this one object which is this model so just like how you can perform an object composition you can also do functional composition as well what that means is you if this were a function rather than being an object and if this was a function rather being an object you can take these two independent functions and you can merge them together and you can create a composite function and this becomes a functional composition so when you pass the data to the first function it can evaluate the data and send it to the second function so the data can flow through these functions and and you can perform the sequence of computations so just like you can perform object composition you can perform functional composition as well and combine functions as it might be useful so so this is this idea can be taken further into programming so I'm going to save this as declarative and functional if you will and and that is basically the power of this kind of programming music and bring these ideas together for these kinds of functional and decorative style of programming well given this of course this leads us to how do we pass a function to another function well for passing functions to enter the function we must be able to represent this function but more important we must be able to get a reference to a function because if you can get a reference to a function you can then pass it around like you can get a reference to an object and you can pass it around so this is where lambdas really come in so what is the lambda expression a lambda expression is an anonymous function that's what it really is so what does it mean an anonymous function well typically what functions really have so you can say that but that a lambda expression so you can say lambda expressions are really anonymous functions so anonymous functions and in general they are also you know expected it could say to be pure functions and what we mean by expected with your functions is you don't mutate these for data you don't have any side effects within these functions so in general you want them to be pure functions so lambda expressions are anonymous functions and they're expected to be pure functions in general that's your expectation based on lambdas but a lambda is a weird name why in the world they would they call it lambda so lambda is because these were just symbols given to expressions in the mathematical term just like you and I would maybe write an equation and you may call it X Y or Z well they decide to call it a lambda so there is no real significance to the word lambda per se it's just a symbol and so lambda expressions on the other hand are anonymous functions but from that point of view you could say what does it really mean for a structure of a lambda expression to be the way it is so for that let's say a normal function has four parts to it it typically contains the name it has a return type it also has potentially you give a parameter list so parameter list and then finally of course you write a body of the function so these are the four things you normally provide for a function imagine you're on a trip and you're allowed to take only two luggages with you and not anything more so what can you minimally take is the question so from a lambda expression point of view you can say lambda expressions only have two out of these four things now let's think about this for a minute land expressions are anonymous they don't have a name so as a result they are pretty much returned without any name you could assign them to a variable but lambdas specifically don't have a name but if you were to look at these four things what is the most important thing of these four things we can agree that the body is the most important because without the body what is the point of even writing a function so a lambda expression contains a body but in addition to the it also contains a parameter list as well because you want to know on what to work on what to operate on so as a result you will typically give a parameter list okay what about the return type well the return type is inferred for a lambda expression and you are not required to specify the type you could optionally specify it but oftentimes you don't have to provide the return type that's figured out on context so that is basically what you have so from that point of view what is the structure of a lambda expression well the structure for lambda expression varies depending on the programming language that you use but in the case of Kotlin similar to Java you have a parameter list and an arrow separated by a body of a function but in the case of Cartland you wrap them into a curly braces so this is basically the structure of the lambda expression is you have the curly braces you have a body a parameter list of the lambda you have an arrow that separates the parameter list from the body now generally speaking you want the body of the function to be a one-line body if you're gonna write a multi-line body that's generally not a good practice as much as possible you want to keep the lambdas as small as possible now what if somebody wants to write a very large lambda with many lines in it well you unfortunately lose some of the benefits of using lambdas when you do that because one of the nice charms of lambda expressions is it's easy to understand the code and when you walk through this functional pipeline you don't want the lambdas to disrupt your flow of reading so you want to keep the lambdas as much as possible to a single line of the body what if you really are figuring out some code and you feel like you have to write a multi-line function for a lambda my recommendation has immediately call for help and and tell people that you're really having bad thoughts and you need some really serious help so so ask for help and avoid writing long lambdas generally I would say that's not a good idea then are exceptions to the rules but in general think twice or thrice before you write long lambdas so that becomes the structure of a lambda expression and you can write those structures very nicely let's talk about using lambdas to solve the problems we want to solve so let's say for a minute we have this collection of numbers we want to start with and given the collection of numbers how would we go about you know iterating and printing the numbers let's take something really simple to work with first of all so given this collection of numbers all I want to do is print these numbers so what I can do here is I can simply say print and print line and a number and I can print it now while that code is an imperative style and the code works this is looping through and you are writing the loop to go through every single element these often are called as external iterators so external iterator is where you manage the iteration you are writing a for loop and saying go to the next element go to the next element go to the next element well typically the signs of this are you would write continue and break and things like that within the loop that's a sign of you controlling the loop in addition to saying what to do for each of the elements in the loop on the other hand what you can actually do is you can use what is called an internal iterator which usually is the functional style of it so internal iterators in this case you can start with numbers dot for each and you can say given a element that is given to you I'm gonna write this a little bit more traditional and we'll come back and talk about this a little bit later so I'm gonna take an element and I'm gonna print that element out in this particular collection so what so what am i doing at this particular point I'm taking these numbers as the collection and iterating over the numbers one at a time and I'm simply printing it out let's make this a little smaller so it's easier to see what the output looks like on the screen so you can see that it printed one two three and then it also printed one two three so this shows you how you can use a very concise code to write internal iterator to lose through and print the value now I used a code which is a little bit verbose here you can minimize the verbosity quite a bit we'll come back and talk about this in just a few minutes but this shows you an example of how you can use lambdas in this case you're not really you're passing creating and passing a lambda to this code but that becomes a really nice way for you to you know use this lambda expression so in this case that is your lambda expression what can you say about the for each function well the for each function is the higher-order function because unlike print line which took an object as a parameter for each is taking an anonymous function as a parameter so as a result the for each is a higher-order function it receives a function as its argument as its parameter and so it's a higher-order function now what you can do with this is a few different things and the first is you can use the implicit parameter to this particular function so what you can do here is you can say rather than calling it as e you can simply say it so by using it you are avoiding passing a explicit parameter in the case of Cartland so this code right here is equivalent to a parameter coming in and the parameter being used in here and that's what you are saying is just use that parameter in here so you can either receive that parameter and use the parameters name in here or you can simply say assume that there's a parameter called it and I'm going to just use it over here and of course if you are doubling the values in this collection you can do at times too much like you can do at times two here as well so that's a very similar way to write that code becomes a lot easier to work with so you can either receive a parameter explicitly or use it so when do you choose what to do if you are lambda hat exactly one parameter then you can easily use it but if your lambda has no parameters at all or it has more than one parameter then it doesn't make sense to use it so don't try to use 81 82 83 that doesn't work so simply just leave it and give a name and use that name what about the name itself you want to give a sensible name for this so rather than calling it KZ and W you want to give a fairly good name that is meaningful so if it's a collection of people you can call it person if you want to and so on so so decide on a fairly good name so it becomes easy for the programmer to read it so that's an example of using an implicit parameter in that particular case but if a function is fairly simple you can use what is called a function reference so let's look at this example for a minute if you take this example what you're doing is you're taking the parameter and you are simply passing it to the print line you're not doing anything really useful so these kinds of lambdas I would like to call them as pass through lambdas a pass through lambda doesn't do any real work it simply takes an input and passes it to something else so when you're here using the pass through lambda it could be passing as an argument or it could be passed as a target but the point is you're not doing much with it it is just a pass through if you're dealing with the past through lambda then what you can do is you can say for each and you can use a function reference rather than using a lambda explicitly so this becomes a nice way to reduce the complexity or the verbosity in the code so the pass through lambda simply says if all I am doing is receiving the parameter and just passing it to another function then simply put double colon and the name of the function if of course it belongs to a class you can refine that colon with the class name object name and things like that so there's a way to use a reference for that too now pass through lambda makes only sense sorry method function reference makes only sense when you're using a pass through lambda if you are doing some other operation with the parameter like I'm multiplying it with a value of two I cannot use a function reference obviously because this is literally to say just pass through the function I don't have any extra work to do so you so what's the model of the story the model of the story is use function references as much as you can because it reduces the verbosity in the code becomes easier to read it less noisy in the code as well so this should be your preferred first of all if you cannot use function reference then use it when you write your lambda because that reduces the noise of receiving that one single parameter if that's what you have so use it when you cannot use a function reference when you cannot use add then and only then provide explicit names for parameters and then write your lambda and when you do please give meaningful names that are easier for the programmers to understand if you're not able to give a good name try gravitating towards using a function reference it's possible that way you can do get rid of it that's a lot better so that's an example of using a function reference in here as you are writing this now what about receiving a lambda we talked about passing the lambda so far but what about receiving a lambda if I want to get the lambda on my hand from as a function create of a function but before we talk about receiving a lambda let's talk about assigning a lambda to a variable and then calling into it so so to understand this let's take a slightly different example I'm gonna say over here print it and and then is equal to now when I called printed it appears like I'm gonna define a variable in this case a constant but because you are functions are anonymous functions you can treat functions as objects you know how you can pass a function to a function just like you pass an object to a function you can start treating fun like they're objects and as a result you can store them into variables so in this case I'm gonna take this function what is the function going to receive as a parameter it's going to receive a number integer as a parameter and what do I want to do with that parameter I just received I'm gonna just print it so I'm gonna say print line number so the print date is going to simply receive that and print it that's all it's going to do so I'm just running this code and seeing what it's going to do well it says cannot infer the type of this parameter specify that explicitly it's complaining well in this particular case as I'm defining this what is the type of the function because I'm assigning a lambda I want you to take a look at this for a minute it is complaining that you want to give a little bit more information about the type of this particular variable so what I'm going to do in this case is I'm gonna say that this is going to be receiving an integer it is going to return a unit it doesn't have any return pipe it's a void which is a unit type that I'm going to return and that's what I'm gonna specify over here and of course in this particular case I can leave out so let's remove this for a second this is going to be the number coming in and then I'm going to return that particular result for us now in this particular case the number is an integer what if I leave out the int from here well when I leave out the int from here you can see it is still happy with it what if I put the int over here and for a minute let's remove it from here again and and run this code and in this case of course it was okay so the panther's input was not really happy for it so without the parentheses it is quite happy so this is one way to define it alternatively you can remove the type from here and if you don't know the type from here this won't work because obviously you're not telling what the type of number is but you can come in here and say this is going to be an int over here and then it returns a unit at this point and and that will work as well so which one do you use among the two I would prefer personally the format over here on this line because that's less noisy so I would rather specify the type in the ammeter rather than for the variable and that way I don't have to worry about the return type that gets inferred in this case you can go either way how do I call this one now so to call this now I'm gonna call print it and then I'm gonna send a forward over here and as you can see it is simply printing the value four so that's a way for you to invoke this so this is simply storing that into a variable that's all we are doing in fact let's put that away here as storing lambda into a variable right that's what we did we just store it into a variable at this point so we can you know use that for other purposes like calling a function on it if you really want to do but on the other hand you can receive lambdas as parameters to functions as well so how do we receive lambdas to functions so to receive lambda in functions let's create a function that would use it so what I'm going to do here is to write a function will call it as compute and the compute function takes an integer as a parameter I'm going to do some computation then I'm gonna say action and and in this case the action is going to receive a double value and it is going to return nothing which the unit so now we are saying that a compute function takes two arguments it is going to take n which is an input integer but it's also going to take a lambda which is an action and and and when you say action well notice n is an integer you said that but action is a function anonymous function so in this case you say it receives a double as its own parameter and returns void a unit which is representing void and you're saying that's what it's going to return from this now within this code you can say action and you can pass some value n times two to it and you could say 2.0 for example 2.1 whatever that you may want to pass so you can take the value and you can pass that value as a parameter to that particular function how would you go about using this well in order to use this I can say compute I can pass a value let's say seven and seven times two point one is going to be result of that particular call that you're going to get but the action is going to be lets say result and all I'm going to do is simply print the result at this point and of course that's a lambda and we know that we have to take the lambdas and wrap them into Curly's so I'm gonna put a curly right here and I'm gonna wrap them right there so that gives us the result of that particular computation so you can see in this case we pass the value seven and we pass the lambda to this function now that's a little verbose code we'll come back and talk about this in a few minutes but that gives you an idea about how to pass lambdas but more important how to receive lambdas as arguments so in this case of course the compute function takes one object N and then a lambda action as its parameters as a result compute is considered to be a higher-order function and that's what we saw how to receive lambdas as a parameter in here that's what we saw in this particular example well quit so far but when you look at my number five it looks a little cluttered but before we go further let's talk about a couple of differences you can do you can create this function and you can argue maybe I'll put an action comma and I will put a n colon integer so I'm gonna take a lambda first and then I'm gonna take integer value after that well if you write the code like this then of course you're gonna pass the code seven like this while this code will work this is pretty noisy well but this is the consequence of taking lambda in the first place or the first position in the parameter list now that's only choice you have on the other hand if you write the function compute a little differently oh as in if you were to go to this function and past the lambda as the last argument so you basically say n comma and then in this case you're going to put the lambda as the very last argument action well if you do it this way when you call compute you can obviously do the following and we saw this work a few minutes ago however there is one benefit to taking lambda as a last argument if you take lambda as a last argument then instead of the above what you can do is you can pass the parameter seven close the parentheses and you can hang the lambda right outside like this now this is possible only when the lambda is the last parameter so when the lambda is the last parameter it gets a special privilege and and I often say this case of treating the last parameter differently he's like how parents treat their last children very special you know that right I know it very well because I was not the last child and I know the conspiracy against this well that's exactly what's happening here it says this is the last parameter oh dear that's so special so as a result it gets treated very you know especially you can close the parentheses don't need to have a comma and then you can put the lambda right outside so this becomes a very nice syntax now in this case of course if your lambda is multi-line it doesn't disturb the flow so as the result I would say this is probably the only exception I follow to the rule are saying don't write multi-line lambda maybe except when it's hanging as the last one maybe that's not that but that bad really at that point so in this this example of course we have a special treatment for the lambda you can put that in the parameter list argument list but why would you you can put it outside without the comma so that becomes a lot easier to work with so that is basically what we saw here is a little special treatment for this lambda that we can gain from so now that we saw how to use a lambda let's talk about some very common functional programming functions now typically speaking if you are programming in the imperative style what do you normally use use for loops and use use if statement and wild statement and so on now some of the times you know programmers come to me and ask hey you're programming and functional programming use filter map and reduce and things like that but what if I need something else they ask a really good question reasonable question what if you need something else but let's step back and ask the question when you program in imperative style what are the things you normally use you use things like if and else you use for loops you use while and these are the structures you find in any language that's imperative it doesn't matter what you program in C or Java in the imperative style or C sharp or Ruby or Python you have these constructs you have a four you have an if you have an else now what if I need something else well you say gosh you're not going to need anything else because these are the primitives of the imperative style of programming these are the primitive operations of imperative set of programming and it's absolutely phenomenal that you can solve any problem with these few structures like for an F else and things like that similarly in functional programming the filter map and reduce are the primitive functions of functional programming and you can solve almost any problem with a combination of these functions very effectively so as a result your tools of the trade really just like for and if an a while you have filter map and reduce available to you so let's talk about filter how does the filter really work so to understand this let's take a list of numbers we'll call it numbers is equal to and let's say list off and we go ahead and take a list of numbers let's say want to tend right here and I want to get only the even numbers in this collection so what I can do is I can print the numbers out and you can see that it's all the numbers in this collection or we can say print line numbers dot filter and then I'm gonna hang it outside like you can see here and I can say it Mar 2 is equal to 0 so this gives you all the even numbers in the collection rather than all the numbers in the collection so that becomes your filter operation so how does the filter actually work a filter works like the gate in a garage so a car pulls in the door may get me open to let the car in and another car pulls in it may let the car in a third car pulls in it doesn't open because this person doesn't have person doesn't have permission to go and they have to go elsewhere so this is going to select and unselect and decide to let one value or not you know another way to look at it is if I give you a bunch of coins and if I ask you to only give me the times in this coins you can take a little coin sorter you can pour the coins over it all the dimes will fall down and the rest of the coins are held behind that's basically how a filter is working so a filter is going to let some values go through and hold off other values and that's an example of how you can use a filter now there are some characteristics of a filter if you really think about it if you think of a filter a filter takes a predicate as a parameter and a filter will give you zero or one or more all the way up to all the elements for example if I say raise your hand and don't you don't have to do it but if I say raise your hand if you're older than one years of age I'm hoping everyone in this room will raise the hand because everybody here is older than one so that is all the element the filter gave everything on the other hand if I say raise your hand if you're older than 120 years of age I'm hoping there's nobody in this room who is older than 100 and if you are you're looking pretty darn good but the point really is that nobody is older than under 20 so the filter will block everything and nothing comes out but if I say raise your hand if you're older than 50 some of us will raise the hand others warn so there'll be less than the full value but greater than zero so that's how filter is working map on the other hand will give us an ability to transform objects in a collection so in this case I can take the filtered value but I can perform another operation with it I can say given these values filtered perform a map and given it x to double the values which are even in numbers so when I run this code this time notice from the output that you are getting it is the double of all the even values in the collection so we have done the filtering but we perform the map up after that what are the categories categories of a map well the number of input is the same as the number of output in the case of a map so if you have seven elements coming in you're gonna have seven elements going out however the type of the output may not be the same the map may give you double values given integer or a string value given an integer if you give me a collection of strings I can give you a collection of length of the strings collection of strings two collection of int for example so there's no guarantee of the type when it comes to maps on the other hand the count will be the same moving forward and that's an example of using a map function well then comes along the reduced function a reduced function is useful to take the collection of data and reduce it to a single value often but could be a collection as well but a reduce is often a termination of the sequence of operation you can reduce it well there are different reduce operations but one special is called the sum operation which is also a reduce and this of course is taking all the even numbers doubling them and performing the total so this gives you the total of all the double of all the values in the collection even number status and that's what you are getting and some is one example of a reduce but you can use other reduce functions just reduce it and you can pass a function to it with multiple per two parameters and that becomes a reduced operation that you can really use and depends on what you're doing you can have different kinds of reduce operation but having said that I want to talk about one other thing that will be very useful for us and and before we talk about it let's understand a little bit about nap so when it comes to map there are two kinds of functions we typically use now when it comes to these functions you need to choose what kind of map operation you want to perform but before we do that part on me let's talk about one thing here so let's take numbers is equal to list off and and let's go ahead and take a list of numbers again a one to ten so given this list of numbers one to ten let's go ahead and say that we are interested in taking these numbers and transforming it and let's say we have a collection of numbers for a minute so if I say one two three is the numbers I have I can clearly ask for number start size and there's no confusion it's a numbers is three but if I on the other hand create a list of a list of 1 2 comma and list of let's say 3 4 & 5 what is the size of the numbers well we know that the size of numbers is going to be 2 at this point because it's a list of lists after all and if I were to print the numbers you will notice that the numbers really is the list of lists you got but on the other hand you can also do something else Val flat and let's say numbers so flattened numbers is equal to number start flatten I'm gonna flatten it then print out flatten number start size but I'm also going to ask it to print the flattened numbers what does flattening really mean imagine you're working with a small child at home and and you walk into a room there are books all over on the floor and books on the floor there are there's one book next to it there's two books next to it there's three books and then there's two books and there's four books and you're seeking the help of the child to organize said but you want to sort the books as well well you tell the child hey take all these books and flatten them on the floor well if you what does that mean well you take the book one leave it like that you take two books and move them next to each other take the three books and put them flat on the on the floor so flattening is you take a list of lists and you flatten it out so if you run this coat this time you can see from the output that you get you have flattened it into one collection so you have a one two and three and four which is a list of lists and you flattened it so you have five elements which are one two three four and five all as part of this one list that is a flat and operation and I want you to keep that in mind for a few minutes about what flattened really means so now that we talked about flattening let's talk about something a little bit more complex talk about maps for a minute when you think of a map you I want to think of two kinds of functions a function f1 which is a one-to-one function so what is a one-to-one function mean you give me one input I'll give you one output it's a one-to-one transformation and and on the other hand I'm gonna think of a function f 2 which is a 1 2 let's say a mini function so one too many functions on the other hand are functions where you give one input I'll give you many output let's look at some examples if I say we have people in this room and I say I warned your first name well that's a one-to-one function given one person I have one first name input this person output is a string which is the first thing that's a one-to-one transformation all I can say given a person I want all your email addresses not just one of them I want all of them why because it's much fun to spam all your email addresses than to spam one of them so I want a collection I want you to give me a collection of all your email addresses that is a one-to-many transformation know what's gonna happen well unfortunately though if you take a list and you put a map and you pass to the map the function f1 what is the result of this you get back a list on the other hand if you take a listing for from a map f do what are you going to get as a result list of lists versus a list of elements so in other words map will perform literally the transformation so you go from a list - a list when the map is given a one-to-one function and you go to a list - a list of lists when you go for her map with the one-to-many function very easy to see this so let's go ahead and say we have a list of numbers so we'll say numbers is equal to let's say list off 1 2 3 now I want to say output numbers dot map given a element I'm gonna say return element plus 1 so this is a one-to-one function given a II give me plus 1 so that's very easy to see you just got a list as a response so what is the output it's a list so list - a list on the other hand if I say number start in map but given an element return to me a list of element minus 1 comma element plus 1 so I'm gonna give you a list of before and after this becomes list of lists isn't it so when I run this code you will notice from the output that what I got as a result is a list of lists now if that's what you wanted that's awesome you are done you can go home but what if you don't want that what if you really wanted so what if you have a one-to-many function many function a but you don't want want a list list but just a single list well if you just want a single list what what can you do you will map it and then you will flatten it isn't it let's see if that works so here's what I'm going to do I'm gonna take numbers and then I'm gonna say map give an element list off II - 1 comma E + 1 let's start with this baby steps first of all so when I run this code the last output is the same as the one before that's exactly what we got but I don't want a list of Lists so what am I going to do I'm gonna take this value and I'm gonna do a flatten on that that's what I'm gonna do isn't it I'm just gonna flatten it so by flattening it what am I gonna get right now so when I've run this code you can see that I got a flat in the list so I don't have a list of list I just have a list so that's great isn't it but what is the disadvantage the disadvantages I had to map it and then have to flatten it but that's two steps why can't they combine them together that'd be really nice isn't it so in other words if you have have a many-to-many function many function but you want a list and not a list of lists as output then use so what should you really use well let's think about this for a minute if I want to combine these two in functional programming you want to merge these two functions into one remember what we talked about we can combine functions to create bigger functions if that's what I want to do I want to map it first and then I want to flatten it so what I really wanted was the following I wanted Matt flatten as one function now okay Maps I want now I want you to do this experiment I know this is odd this is awkward and if you don't feel comfortable doing it in public I recommend you try this alone you know when nobody is watching try saying Mack flat just try it out a little bit mat flat what did you notice it hurts over here doesn't it mat flat now imagine the functional programmers created map flat 300 years later you will see some humans with deform the jaw and they will look and say you must be a functional programmer how do you know because you look weird with your jaw deformed these people saved humanity they realized math flag is going to end up more dental work for people so they saved the world by calling it black math now say that aloud flatmap see how it rolls off the tongue flat mat so this is why they called it black map so flat map is actually not mat flat but thankfully they called it flat map so but when you're doing flat map you're really mapping and flattening it and so when you look at the output of this you notice that's exactly what you got you mapped it and you flattened it so flat map is really for many to 1 sorry 1 to many functions so when you have a one-to-many function you want not a list of lists as an output but you only want a list as output then you use what is called flat map so a flat map is useful for a one-to-many transformation so this is something you can remember in your mind use map for one-to-one use flat map for one-to-many when the result should be combined into one flattened map and that's what you're gonna use for that purpose so that gives you an idea about how we can use that very nicely and hopefully that gives you an idea about what and when to use a flat map so that map gives you that ability to smooth out the collection now having said that there is one other small detail maybe not so small we need to be really aware of and that is what is the cost of evaluation what is the expense how much work are we going to do so to understand this let's take some numbers is equal to and in this case lists off 1 2 3 5 4 6 7 8 let's say 9 and 10 but the problem I'm going to give you is the following find them let's say a double off the first number greater than 3 and is even so if I give you this problem find the first number greater than 3 and even but find a double of it let's do it with our human eyes and hands what would I do is 1 greater than 3 no 2 no 3 no 5 oh yes 5 is better than 3 is 5 even no is 4 greater than 3 yes it is is four even yes double 4 we got a result 8 stop you're not going to touch 6 7 and anything after that so that is efficient if we do it that way now let's see if that actually is true so let's create a is greater than which takes a number integer and it's going to return n is greater than 3 I'm going to provide a function is even and the easte even function takes the number n and it's going to return let's say n times 2 so with that said what do i what sorry n mod 2 is equal to 0 so with that said what am I going to really do with this code I want to call a print line number start in this case filter and I'm going to pass through the filter is greater than 3 and then I'm gonna call a filter again and pass do it east even and then finally I'm gonna call a map function and pass to it double it where the double it function is going to simply say that it is going to take a value N and it's going to return to us let's say equal to n times 2 now if I were to call this I'm gonna say dart find first so I'm gonna say first and return the first value from from this particular collection what does the result say yeah the good news the result is 8 well that's great the result is 8 but what what is the amount of work we did this is where the problem comes in if I were to put an int over here and then say in here if I say print line is greater than is greater than T is called for called let's say far and I'm going to print the value of n when I run this code unfortunately notice that it is going to call of course I got to return the result don't I return n greater than 3 so if I run this code unfortunately notice what it's going to do it is calling the East greater than 3 what did I do wrong boolean right I'm sleeping at the wheel so this is going to be a boolean result of course so if I run this code what it is doing is it is going to call this function for every single value all the way up to 10 how sad that is in fact if you go a little further and try this if I put a boolean here also and then of course if I were to return let's say n mod 2 is equal to 0 but before I do that print line and I say is even called let's say far and I'm going to print the number for which it is called you can see that all that expands that we incur which is not what you really want to do because that's not very efficient but before we go further I want to mention one quick thing over here and that is if you ask me what is the really the essence of functional programming and I'm gonna say that functional programming is equal to and I'm gonna add in this case it is object sorry it is a sorry functional composition plus the use of so absolutely composition plus the use of lazy evaluation so in other words if you ask me what about object render programming I'm gonna say polymorphism is to polymorphism is to or be as lazy evaluation is to functional programming if you want to do OB why would you bother if you don't have polymorphism in the same note I would say lazy evaluation is asked critical for functional programming so when you look at this example it did all the extra work for us to throw most of its most most of it out so I'm gonna save this away here as from eager eager to and what you can do though you gotta be careful with this is you can go in and say yes I do want laziness and you put a sequence over here and when you turn that into a sequence when you run the code you notice that in this case you're not doing all that extra work you did not touch any value pass the value six at this point so the sequence gives you laziness of evaluation and so you don't want to be running on a list directly if you have a very large collection and and if you want lazy valuation you want rate on the sequence rather than running it on the list because then it is going to evaluate lazily so using sequence as sequence in Cartland gives you behavior like using streams in Java in Java you don't have the filter and map on list you only have them on stream for a good reason because they want those to be done only one way which is lazy valuation Carlin gives you the choice but you got to be careful what you're using otherwise you end up using the wrong stuff so from from you know eager of elevation to lazy evaluation and so that becomes very efficient from the functional programming point of view so so that gives you an idea about how we can use sequences to get laziness so with that said cotton gives you a fairly decent amount of choice to do functional programming as much as other programming models you have to choose wisely and apply them if you're interested in downloading the code examples I showed you here you can download them from my website right here I just as I wrote it I saved it I'll zip it and post it in about ten minutes from now you should be able to see it on my site after that and if you're interested deep into this further please take a look at programming Cartland which is right now in beta release it'll be released within a month or two in a production release after that so please take a look at that also hope that was useful thanks for coming [Applause]
Info
Channel: Devoxx
Views: 8,628
Rating: undefined out of 5
Keywords: DVXPL19
Id: pFbDZQ9M76Y
Channel Id: undefined
Length: 53min 40sec (3220 seconds)
Published: Wed Jul 31 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.