Learniverse

Introduction to Functional Programming in Kotlin

00:00

All right. Let's get started. Welcome to the session on functional programming in Kotlin.

00:15

I'm going to talk about a little bit about functional programming and then show a few things we can do with Kotlin in terms of writing functional style code.

00:24

And I'll also talk about what it means to be functional along the way as well.

00:29

If you don't have any questions or comments, I'll be thrilled to hear from you.

00:33

Just begin speaking, even though if I may be looking at your direction, I may not be paying attention to you.

00:39

So draw my attention and then, you know, speak up. I'll be more than happy to listen to you.

00:44

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

00:53

quite a bit of complexity in code. Well, let's talk about imperative versus declarative and then a little bit about functional style, just to set the stage for what does it really mean to do this.

01:03

Well, in the imperative style of programming, we show what to do, but also we tell how to do it.

01:09

So the entire burden of writing the code with all the details falls on our shoulders.

01:15

So let's look at an example really quickly. I want to talk, take numbers as an example is equal to list off.

01:22

Let's go ahead and say, I have a list of numbers. Let's say, 1 to 10.

01:26

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.

01:40

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?

01:48

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.

01:56

Then you can say far and you can provide a number and the number coming from numbers, if you will, which is this collection of numbers you want to deal with.

02:06

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 0 at this point.

02:13

But what you can then do here as you can say, if the number that is given to us is even numbers.

02:20

So you can say, mark 2 is equal to 0 and if it's even number, then you can say a total plus equal to the given number times 2.

02:28

And you can then start totaling the double of all the values in the collection.

02:33

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 sits on our shoulders.

02:49

And that is the imperative style of programming. We all have done that in language as before.

02:55

The caroling does not prevent you from doing it. If that is the choice for you, you can still do that in caroling.

03:01

The declarative style of programming is where you focus on telling what to do and not how to do it.

03:08

So you can simply say, what you want, rather than detailing the steps of how to do it.

03:14

So this is like talking to one 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.

03:23

So you are calling functions that can do the work for you rather than having to spend time on low-level details.

03:31

If you look at the code, we just wrote, you have to say how to perform the total of the product.

03:37

You have to write the piece of code rather than just directing to say, go do this for me.

03:41

So declarative style is where you can focus on what and not focus on the how.

03:46

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.

03:55

I'm going to save this along as we speak. So I'm just going to say imperative right there and save it.

04:00

But I'm going to talk about the declarative style. What does it mean to be declarative?

04:05

Well, to understand what declarative means. So imperative is where you tell what and also how.

04:13

Well, declarative on the other hand is tell what and not how.

04:18

So you're able to focus on just the what that your goal when it comes to doing that.

04:23

Now, what is really cool about functional style is functional style is declarative plus the use of what are called higher order functions.

04:32

So this gives you a nice way to build on the concepts of functional programming with declarative and bringing in the higher order functions.

04:40

So that makes the question, what does it really mean a higher order functions?

04:44

Well, I'm going to 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.

04:52

So a normal function of regular function, what does it really mean?

04:56

Well, we pass object typically to functions and we do this all the time. We pass objects to functions.

05:04

And so these are normal functions. We create object in a function. So we do this all so quite often.

05:12

And then finally, of course, we return object from a function.

05:18

And these are the things we normally do when it comes to programming. We pass objects to functions.

05:23

We create objects within functions. We return objects from functions as well.

05:28

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.

05:38

And that is, we pass function to function. We create function within function and also we may return a function from a function.

05:47

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.

05:56

It may receive, create or return functions as well. And what are the cool things about doing this is, in addition to doing object composition, we can also do functional composition.

06:08

Now, if you really think about it, if I were to think about object oriented programming, I could say that here is an example of a bottle.

06:17

But from the other point of view, object oriented programming point of view, what is a bottle made up of? This is what we call as aggregation.

06:25

So aggregation says, this bottle is made up of the container's plastic. It contains a nice label. It also contains a lid and maybe it contains liquid inside of that.

06:38

So you can say that there are four objects that came together to create this one object which is this bottle. So just like how you can perform object composition, you can also do functional composition as well.

06:53

What that means is, if this were a function rather than being an object and if this was a function rather than being an object, you can take these two independent functions and you can merge them together and you can create a composite function.

07:07

And this becomes a functional composition. So when you pass a data to the first function, you can evaluate the data and send it to the second function so the data can flow through these functions and you can perform the sequence of computations.

07:22

So just like you can perform object composition, you can perform functional composition as well and combine functions as it might be useful.

07:31

So this idea can be taken further into programming. So I'm going to save this as declarative and functional if you will.

07:40

And that is basically the power of this kind of programming using and bring these ideas together for these kinds of functional and decorative style of programming.

07:48

Well given this of course, this leads us to how do we pass a function to another function?

07:55

Well for passing functions to another function, we must be able to represent this function, but more important, we must be able to get a reference to a function.

08:05

Because if you can get an 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.

08:12

So this is where land does really come in. So what is the lambda expression?

08:18

A lambda expression is an anonymous function that's what it really is. So what does it mean an anonymous function?

08:25

Well typically, what do functions really have? So you can say that, but that a lambda expression, so you can say lambda expressions are really anonymous functions.

08:37

So anonymous functions and in general they are also, you know, expected if could say to be pure functions.

08:45

And what we mean by expected if your function says, you don't mutate these data, you don't have any side effects within these functions.

08:53

So in general, you want them to be pure functions.

08:56

So lambda expressions are anonymous functions and they're expected to be pure functions in general, that you will expectation based on lambdas.

09:03

But a lambda is a weird name, why in the world they would they call it lambda.

09:08

So lambda is because these were just symbols given to expressions in the mathematical term.

09:14

Just like you and I would maybe write an equation and you may call it x, y, or z, while data is at a call it a lambda.

09:22

So there's no real significance to the word lambda per say, it's just a symbol.

09:26

And so lambda expressions on the other hand are anonymous functions.

09:30

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?

09:37

So for that let's say a normal function has four parts to it.

09:42

It typically contains a name, it has a return type, it also has potentially you give a parameter list, so parameter list,

09:52

and then finally of course you write a body of the function.

09:55

So these are the four things you normally provide for a function.

09:59

Imagine you're on a trip and you're allowed to take only two legages with you and not anything more.

10:05

So what can you minimally take is the question.

10:08

So from a lambda expression point of view, you can say lambda expressions only have two out of these four things.

10:16

Now let's think about this for a minute.

10:18

Lambda expressions are anonymous, they don't have a name.

10:22

So as a result, they are pretty much returned without any name.

10:26

You could assign them to a variable, but lambda specifically don't have a name.

10:31

But if you were to look at these four things, what is the most important thing of these four things?

10:37

We can agree that the body is the most important because without the body, what is the point of even writing a function?

10:45

So a lambda expression contains a body, but in addition to that, it also contains a parameter list as well,

10:53

because you want to know on what to work on, what to operate on.

10:57

So as a result, you would typically give a parameter list.

11:01

Hey, what about the return type?

11:03

Well, the return type is inferred for a lambda expression and you're not required to specify the type.

11:09

You could optionally specify it, but oftentimes you don't have to provide the return type that's figured out on context.

11:15

So that is basically what you have.

11:17

So from that point of view, what is the structure of a lambda expression?

11:22

Well, the structure of a lambda expression varies depending on the programming language that you use.

11:27

But in the case of Kotlin, similar to Java, you have a parameter list, an arrow separated by a body of a function.

11:36

But in the case of Kotlin, you wrap them into a curly braces.

11:40

So this is basically the structure of a lambda expression.

11:43

You have the curly braces, you have a parameter list of the lambda.

11:48

You have an arrow that separates the parameter list from the body.

11:53

Now, generally speaking, you want the body of the function to be a one-line body.

11:59

If you're going to write a multi-line body, that's generally not a good practice.

12:04

As much as possible, you want to keep the lambdas as small as possible.

12:09

Now, what if somebody wants to write a very large lambda with many lines in it?

12:15

Well, you unfortunately lose some of the benefits of using lambdas when you do that.

12:20

Because one of the nice charms of lambda expressions is it's easy to understand the code.

12:25

And when you walk through this functional pipeline, you don't want the lambdas to disrupt your flow of reading.

12:31

So you want to keep the lambdas as much as possible to a single line of the body.

12:36

What if you really are figuring out some code and you feel like you have to write a multi-line function for a lambda?

12:44

My recommendation is immediately called for help and tell people that you're really having back thoughts and you need some really serious help.

12:52

So as for help and avoid writing long lambdas, generally I would say that's not a good idea.

12:57

There are exceptions to the rules, but in general, think twice or twice before you write long lambdas.

13:02

So that becomes the structure of a lambda expression and you can write those structures very nicely.

13:07

Let's talk about using lambdas to solve the problems we want to solve.

13:12

So let's say for a minute, we have this collection of numbers we want to start with.

13:18

And given the collection of numbers, how would we go about iterating and printing the numbers?

13:24

Let's take something really simple to work with first of all.

13:27

So given this collection of numbers, all I want to do is print these numbers.

13:31

So what I can do here is I can simply say print and print line and number and I can print it.

13:38

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.

13:46

These often are called as external iterators.

13:50

So external iterator is where you manage the iteration.

13:55

You are writing a four loop and saying go to the next element, go to the next element, go to the next element.

14:00

Well, typically the signs of this are you write continue and break and things like that within the loop.

14:06

That's a sign of you controlling the loop in addition to saying what to do for each of the elements in the loop.

14:13

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.

14:21

So internal iterators, in this case, you can start with numbers.for each.

14:27

And you can say given an element that is given to you, I'm going to write this a little bit more traditional and we'll come back and talk about this a little bit later.

14:36

So I'm going to take an element and I'm going to print that element out in this particular collection.

14:41

So what I'm 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.

14:50

Let's make this a little smaller so it's easier to see what the output looks like on the screen.

14:55

So you can see that it printed one to three and then it also printed one to three.

14:59

So this shows you how you can use a very concise code to write internal iterator to loop through and print the value.

15:07

Now I used a code which is a little bit verbose here.

15:10

You can minimize the verbosity quite a bit.

15:12

We'll come back and talk about this in just a few minutes.

15:14

But this shows you an example of how you can use lambdas in this case.

15:19

You're not really, you're passing, creating and passing a lambdas to this code, but that becomes a really nice way for you to use this lambdas expression.

15:28

So in this case that is your lambdas expression.

15:31

What can you say about the for each function?

15:34

Well the for each function is a higher order function because unlike print line which took an object as a parameter for each is taking an anonymous function as a parameter.

15:48

So as a result the for each is a higher order function.

15:52

It receives a function as its argument as its parameter and so it's a higher order function.

15:58

Now what you can do with this is a few different things.

16:01

And the first is you can use the implicit parameter to this particular function.

16:07

So what you can do here is you can say rather than calling it as E you can simply say it.

16:14

So by using it you are avoiding passing a explicit parameter in the case of Cartland.

16:21

So this code right here is equivalent to a parameter coming in and the parameter being used in here.

16:29

And that's what you're saying is just use that parameter in here.

16:33

So you can either receive that parameter and use that parameters name in here or you can simply say assume that there's a parameter called it.

16:43

And I'm going to just use it over here. And of course if you're doubling the values in this collection you can do a times two much like you can do a times two here as well.

16:52

So that's a very similar way to write that code becomes a lot easier to work with.

16:57

So you can either receive a parameter explicitly or use it.

17:01

So when do you choose what to do?

17:03

If you are lambda has exactly one parameter then you can easily use it.

17:10

But if you're lambda has no parameters at all or it has more than one parameter then it doesn't make sense to use it.

17:18

So don't try to use it one it to it three that doesn't work. So simply just leave it and give a name and use that name.

17:25

What about the name itself? You want to give a sensible name for this.

17:29

So rather than calling it KZ and W you you want to give a fairly good name that is meaningful.

17:36

If it's a collection of people you can call it first and if you want to and so on.

17:41

So so decide on a fairly good name so it becomes easy for the programmer to read it.

17:46

So that's an example of using an implicit parameter in that particular case.

17:50

But if a function is fairly simple you can use what is called a function reference.

17:57

So let's look at this example for a minute.

17:59

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.

18:08

You're not doing anything really useful.

18:10

So these kinds of lambdas I would like to call them as pass through lambdas.

18:15

A pass through lambda doesn't do any real work.

18:19

It simply takes an import and passes it to something else.

18:23

So when you're using a pass through lambda it could be passing as an argument or it could be passed as a target.

18:29

But the point is you're not doing much with it. It is a pass through.

18:33

If you're dealing with the pass 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.

18:44

So this becomes a nice way to reduce the complexity of the verbosity in the code.

18:51

So the pass through lambda simply says if all I'm doing is receiving the parameter and just passing it to another function then simply put double colon and the name of the function.

19:03

If of course it belongs to a class you can refine that colon with the class name object name and things like that.

19:09

So there's a way to use a reference for that too.

19:12

Now a pass through lambda makes only sense.

19:14

Sorry a method function reference makes only sense when you're using a pass through lambda.

19:19

If you are doing some other operation with the parameter like I'm multiplying with the 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.

19:34

So what's the model of the story?

19:36

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.

19:47

Less noisy in the code as well. So this should be your preferred first of all.

19:52

If you cannot use a function reference then use it when you write your lambda because that reduces the noise of receiving that one single parameter if that's all you have.

20:05

So use it.

20:06

When you cannot use a function reference when you cannot use it then and only then provide explicit names for parameters and then write your lambda.

20:15

And when you do please give meaningful names that are easier for the programmers to understand.

20:20

If you're not able to give a good name try gravitating towards using a function reference it's possible that way you can get rid of it that's a lot better.

20:29

So that's an example of using a function reference in here as you are writing this.

20:35

Now what about receiving a lambda we talked about passing the lambda so far the what about receiving a lambda if I want to get the lambda on my hand from as a function create of a function.

20:48

But before we talk about receiving a lambda let's talk about assigning a lambda to a variable and then calling into it.

20:56

So to understand this let's take a slightly different example I'm going to say over here printed and and then is equal to now when a call printed it appears like I'm going to define a variable in this case a constant.

21:11

But because your functions are anonymous functions you can create functions as objects you know how you can pass a function to a function just like you pass an object to a function.

21:22

And you can start treating functions like they are objects and as a result you can store them into variables.

21:29

So in this case I'm going to take this function what is the function going to receive as a parameter it's going to receive a number integer as a parameter.

21:39

And what do I want to do with that parameter I just received I'm going to just print it so I'm going to say print line number.

21:46

So the print it 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.

21:55

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.

22:09

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.

22:16

So what I'm going to do in this case is I'm going to say that this is going to be receiving an integer it is going to return a unit it doesn't have any return type it's a void which is a unit type that I'm going to return and that's what I'm going to specify over here.

22:31

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.

22:41

Now in this particular case the number is an integer what if I leave out the int from here while when I leave out the int from here you can see it is still happy with it.

22:50

What if I put the int over here and for a minute let's remove it from here again and run this code and in this case of course it was okay.

22:59

So the parenthesis I put was not really happy for it so without the parenthesis it is quite happy so this is one way to define it alternatively you can remove the type from here.

23:09

And if you remove 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.

23:19

And then it returns a unit at this point 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.

23:33

So I would rather specify the type in the parameter 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.

23:42

How do I call this one now so to call this now I'm going to call printed and then I'm going to send a forward over here and as you can see it is simply printing the value for.

23:52

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 variable right that's what we did we just stored into a variable at this point.

24:07

So we can use that for other purposes like calling a function on it if you really wanted to but on the other hand you can receive lambda as parameters to functions as well.

24:19

So how do we receive lambda's to functions so to save 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 and

24:36

integer as a parameter I'm going to do some computation then I'm going to say action and and in this case the action is going to receive a double value and it is going to return nothing which is a unit so now we are saying that a compute function takes two arguments.

24:54

It is going to take a n which is an input integer but it's also going to take a lambda which is an action and and when you say action well notice n is an integer you said that.

25:05

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.

25:19

Now within this code you can say action and you can pass some value n times 2 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.

25:37

How would you go about using this when in order to use this I can say compute I can pass a value let's say 7 and 7 times 2.1 is going to be the result of that particular call that you're going to get.

25:50

But the action is going to be let's 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.

26:01

To take the lambdas and wrap them into curly so I'm going to put a curly right here and I'm going to wrap them right there so that gives us the result of that particular computation.

26:12

So you can see in this case we passed the value 7 and we passed the lambda to this function.

26:18

Now that's a little verbose code will 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.

26:28

So in this case of course the compute function takes one object n and then an lambda action as its parameters as a result compute is considered to be a higher order function.

26:40

And that's what we saw how to receive lambdas as a parameter in here that's what we saw in this particular example.

26:46

Well with so far when you look at line number five it looks a little cluttered but before we go further let's talk about a couple of differences you can do.

26:56

You can create this function and you can argue maybe I'll put an action common and I'll put an n colon integer so I'm going to take a lambdas first and then I'm going to take a integer value after that.

27:12

Well if you write the code like this then of course you're going to pass the code 7 like this while this code will work this is pretty noisy.

27:22

Well but this is the consequence of taking lambdas in the first place are the first position in the parameter list.

27:30

Now that's only choice you have on the other hand if you write the function compute a little differently.

27:37

As in if you work to go to this function and pass 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.

27:52

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.

28:00

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 7 close the parenthesis and you can hang the lambda right outside like this now this is possible only when the lambda is the last parameter.

28:27

So when the lambda is the last parameter it gets a special privilege and and I often say this case of reading the last parameter differently is like how parents treat their last children very special.

28:43

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.

28:53

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 parenthesis.

29:04

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 disappear the flow.

29:17

So as a result I would say this is probably the only exception I followed the rule are saying don't write multi line lambda may be except when it's hanging as the last one maybe that's not that bad really at that point.

29:30

So in this this example of course we have a special treatment for the lambda you can put it 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.

29:44

So that is basically what we saw here is a little special treatment for this lambda that we can gain from.

29:51

So now that we saw how to use a lambda let's talk about some very common functional programming functions.

29:59

Now typically speaking if you are programming in the competitive style what do you normally use use for loops and use use if statement and wild statement and so on.

30:11

Now some of the times you know programmers come to me and ask hey you're programming in functional programming use filter map and reviews and things like that but what if I need something else they ask really good question reasonable question what if you need something else but let's tip back and ask the question when you program in competitive style what are the things you normally use you use things like if and else you use for loops you use wild and these are the structures.

30:40

You find in any language that's imperative it doesn't matter what you program in sea or Java in the imperative style or sea sharp or ruby or python you have these constructs you have a far 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.

31:06

These are the primitive operations of imperative style of programming and it's it's absolutely phenomenal that you can solve any problem with these few structures like foreign if else and things like that similarly in functional programming the filter map and reviews are the primitive functions of functional programming and you can solve almost any problem with the combination of these functions very effectively.

31:31

So as a result you are tools of the trade really just like for and if and a while you have filter map and reviews available to you.

31:40

So let's talk about filter how does the filter really work so to understand this let's take a list of numbers will call it numbers is equal to and let's say list off and we'll 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.

31:59

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 going to hang it outside like you can see here and I can say it more to is equal to zero so this gives you all the even numbers in the collection rather than all the numbers in the collection.

32:23

So that becomes your filter operation. So how does the filter actually work a filter works like the get in a garage.

32:31

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.

32:41

It doesn't open because this person doesn't have person doesn't have permission to go and they have to go elsewhere.

32:46

So this is going to select and unselect and decide to let one value or not. In 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 dimes 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.

33:11

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.

33:18

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.

33:35

For example if I say raise your hand and 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.

33:48

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 120.

33:58

And if you are you're looking pretty darn good. But the point really is that nobody is older than 120 so the filter will block everything and nothing comes out.

34:08

But if I say raise your hand if you're older than 50 some of us will raise the hand others won't. So there'll be less than the full value but greater than zero.

34:17

So that's how filter is working. Map on the other hand will give us an ability to transform objects in a collection.

34:25

So in this case I can take the filtered value but I can perform another operation with it.

34:31

I can say given these values filtered perform a map and given it times two double the values which are even in numbers.

34:41

So when I run this code this time notice from the output that you're getting it is the double of all of even values in the collection.

34:49

So we are done the filtering but we perform the map up after that. What are the characteristics of a map.

34:56

Well the number of input is the same as the number of output in the case of a map.

35:01

So if you have seven elements coming in you're going to have seven elements going out. However the type of the output may not be the same.

35:08

The map may give you double values given integer or a string value given integer. If you give me a collection of strings I can give you a collection of length of

35:17

the strings collection of strings to collection of int for example. So there's no guarantee of the type when it comes to maps.

35:23

On the other hand the count will be the same moving forward and that's an example of using a map function.

35:29

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.

35:41

But a reduce is often a termination of this sequence of operation. You can reduce it. Well there are different reduced operations.

35:48

But one special is called the sum operation which is also a reduce.

35:54

And this of course is taking all the even numbers doubling them and performing the total.

36:01

So this gives you the total of all the double of all the values in the collection even numbers that is.

36:08

And that's what you're getting and some is one example of a reduce.

36:12

But you can use other reduce functions as reduce it and you can pass a function to it with multiple two parameters and that becomes a reduce operation that you can really use and depends on what you're doing.

36:23

You can have different kinds of reduce operation.

36:25

But having said that I want to talk about one other thing that will be very useful for us.

36:31

And before we talk about it let's understand a little bit about map.

36:36

So when it comes to map there are two kinds of functions we typically use.

36:41

Now when it comes to these functions you need to choose what kind of map operation you want to perform.

36:46

But before we do that pardon me let's talk about one thing here.

36:50

So let's take numbers is equal to list off and let's go ahead and take a list of numbers again 1 to 10.

36:57

So given this list of numbers 1 to 10 let's go ahead and say that we are interested in taking these numbers and transforming.

37:05

And let's say we have a collection of numbers for a minute.

37:10

So if I say 1 to 3 is the numbers I have.

37:13

I can clearly ask for numbers dot size and there's no confusion.

37:18

It's numbers is 3.

37:20

But if I on the other hand create a list of a list of 1 to comma and list of let's say 3, 4 and 5.

37:30

What is the size of the numbers?

37:33

Well we know that the size of numbers is going to be 2 at this point because it's a list of list after all.

37:40

And if I were to print the numbers you will notice that the numbers really is the list of list you got.

37:46

But on the other hand you can also do something else.

37:50

Val flattened let's say numbers.

37:54

So flatten numbers is equal to numbers dot flatten.

37:58

I'm going to flatten it then print out flatten numbers dot size but I'm also going to ask it to print the flatten numbers.

38:06

What is flattening really mean?

38:08

Imagine you're working with a small child at home and you walk into a room and there are books all over on the floor.

38:15

And the 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.

38:24

And you're sitting the help of the child to organize it but you want to sort the books as well.

38:29

Well you tell the child hey take all these books and flatten them on the floor.

38:35

Well if you what does that mean?

38:37

Well you take the book one leave it like that you take two books and move them next to each other.

38:42

Take the three books and put them flat on the floor.

38:45

So flattening is you take a list of list and you flatten it out.

38:50

So if you run this code this time you can see from the output that you get you have flattened it into one collection.

38:58

So you have a one two and three and four which is the list of list and you flattened it.

39:03

So you have five elements which are one two three four and five all as part of this one list.

39:09

That is a flattened operation and I wanted to keep that in mind for a few minutes about what flattened really means.

39:15

So now that we talked about flattening let's talk about something a little bit more complex.

39:21

Talk about maps for a minute when you think of a map you I want to think of two kinds of functions.

39:27

A function f one which is a one to one function.

39:32

So what does a one to one function mean?

39:34

You give me one input I'll give you one output.

39:37

It's a one to one transformation and on the other hand I'm going to think of a function f two which is a one two.

39:44

Let's say a many function.

39:47

So one to many functions on the other hand or functions where you give one input I'll give you many output.

39:54

Let's look at some examples.

39:56

If I say we have people in this room and I say I want your first name.

40:02

Well that's a one to one function given one person I have one first name.

40:07

Input is person output is a string which is the first name that's a one to one transformation.

40:13

Or I can say given a person I want all your email addresses not just one of them.

40:19

I want all of them why because it's much fun to spam all your email addresses then to spam one of them.

40:26

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.

40:33

Now what's going to happen what unfortunately though if you take a list and you put a map and you pass to the map the function f one what is the result of this you get back a list.

40:47

On the other hand if you take a list and perform a map f two what are you going to get as a result list of list versus a list of elements.

40:58

So in other words map will perform literally the transformation.

41:03

So you go from a list to a list when a map is given a one to one function and you go to a list to a list of list when you go for a map with a one to many function.

41:14

Very easy to see this.

41:16

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 of one to three.

41:24

Now I want to say output numbers dot map given a element.

41:29

I'm going to say return element plus one.

41:33

So this is a one to one function given a e give me e plus one.

41:39

So that's very easy to see you just got a list as a response.

41:43

So what is the output it's a list.

41:45

So list to a list on the other hand if I say numbers dot map.

41:51

But given a element return to me a list of element minus one comma element plus one.

41:58

So I'm going to give you a list of before and after this becomes list of list is in it.

42:04

So when I run this code you will notice from the output that what I got as a result is a list of list.

42:11

Now if that's what you wanted that's awesome you are done you can go home.

42:16

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.

42:26

But you don't want a list of list but just a single list.

42:36

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.

42:45

Let's see if that works. So here's what I'm going to do.

42:48

I'm going to take numbers and then I'm going to say map given an element list of e minus one comma e plus one.

42:58

Let's start with this baby steps first of all.

43:00

So when I run this code the last output is the same as the one before that's exactly what we got.

43:06

But I don't want the list of list.

43:08

So what am I going to do? I'm going to take this value and I'm going to do a flatten on that.

43:14

That's what I'm going to do isn't it. I'm just going to flatten it.

43:18

So by flattening it what am I going to get right now.

43:21

So when I run this code you can see that I got a flattened list.

43:26

So I don't have a list of list. I just have a list.

43:30

So that's great isn't it.

43:32

But what is the disadvantage? The disadvantage is I have to map it and then I have to flatten it.

43:40

But that's two steps. Why can they combine them together? That would be really nice isn't it.

43:46

So in other words, if you have a many to many function, many function, but you want a list and not a list of list as output, then use.

44:04

So what should you really use? Well let's think about this for a minute.

44:08

If I want to combine these two in functional programming, you want to merge these two functions into one.

44:15

Remember what we talked about. We can combine functions to create bigger functions.

44:19

If that's what I want to do, I want to map it first and then I want to flatten it.

44:26

So what I really wanted was the following. I wanted map flatten as one function.

44:33

Now okay, map flat I want. Now I want you to do this experiment. I know this is odd, this is awkward.

44:40

And if you don't feel comfortable doing it in public, I recommend you try this alone when nobody is watching.

44:47

Try saying, map flat. Just try it out a little bit, map flat.

44:53

What did you notice? It hurts over here, doesn't it?

44:57

map flat. Now imagine the functional programmers created map flat.

45:05

300 years later, you will see some humans with deformed jaw.

45:12

And they will look and say, you must be a functional programmer. How do you know?

45:16

Because you look weird with your jaw deformed. These people saved humanity.

45:22

They realized map flat is going to end up more dental work for people.

45:29

So they saved the world by calling it flat map. Now say that allowed flat map.

45:37

See how it rolls off the tongue flat map. So this is why they called it flat map.

45:44

So flat map is actually map flat.

45:48

But thankfully they called it flat map.

45:52

So when you're doing flat map, you're really mapping and flattening it.

45:57

And so when you look at the output of this, you notice that's exactly what you got.

46:03

You mapped it and you flattened it. So flat map is really for many to one, sorry, one to many functions.

46:11

So when you have a one to many function, you want not a list of list as an output.

46:16

But you only want a list as an output. Then you use what is called flat map.

46:23

So flat map is useful for a one to many transformation.

46:27

So this is something you can remember in your mind. Use map for one to one.

46:32

Use flat map for one to many. When the result should be combined into one flat and map.

46:38

And that's what you're going to use for that purpose. So that gives you an idea about how we can use that very nicely.

46:43

And hopefully that gives you an idea about what and when to use a flat map.

46:47

So flat map gives you that ability to smooth out the collection.

46:51

Now having said that, there is one other small detail. Maybe not so small.

46:56

We need to be really aware of. And that is, what is the cost of evaluation?

47:01

What is the expense? How much work are we going to do?

47:05

What to understand this? Let's take some numbers is equal to.

47:09

And in this case, list of one, two, three, five, four, six, seven, eight.

47:15

Let's say nine and ten. But the problem I'm going to give you is the following.

47:21

Find them. Let's say a double of the first number greater than three and is even.

47:29

So if I give you this problem, find the first number greater than three and even find a double of it.

47:34

Let's do it with our human eyes and hands. What would I do?

47:38

Is one greater than three, no, two, no, three, no, five. Oh, yes, five is greater than three.

47:43

Is five even? No. Is four greater than three? Yes, it is.

47:48

Is four even? Yes. Double four, regardless of a stop.

47:52

You are not going to touch six, seven and anything after that.

47:57

So that is efficient if we do it that way.

48:00

Now let's see if it actually is true. So let's create a e's greater than, which takes a number integer.

48:07

And it's going to return n is greater than three. I'm going to write a function e's even.

48:12

And the e's even function takes a number n and it's going to return, let's say, n times two.

48:18

So with that said, what do I, sorry, n mark two is equal to zero.

48:23

So with that said, what am I going to really do with this code?

48:27

I want to call a print line numbers dot in this case filter.

48:33

And I'm going to pass to the filter e's greater than three.

48:37

And then I'm going to call a filter again and pass to it e's even.

48:41

And then finally, I'm going to 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.

48:53

And it's going to return to us, let's say equal to n times two.

48:58

Now if I were to call this, I'm going to say dot find first.

49:03

So I'm going to say first and return the first value from, from this particular collection.

49:09

What does the result say? Yeah, the good news, the result is eight.

49:13

Well, that's great, the result is eight, but what, what is amount of work we did?

49:17

This is where the problem comes in.

49:19

If I were to put an int over here and then say in here.

49:23

If I say print line e's greater than e's greater than t is called for called, let's say far.

49:33

And I'm going to print the value of n.

49:35

When I run this code, unfortunately, notice that it is going to, of course, I got to return the result.

49:42

Don't I return n greater than three.

49:44

So if I run this code, unfortunately, notice what it's going to do.

49:48

It is calling the e's greater than three, what did I do wrong?

49:52

Boolean, right? I'm sleeping at the wheel.

49:54

So this is going to be a Boolean result, of course.

49:56

So if I run this code, what it is doing is it is going to call this function for every single value,

50:04

all the way up to 10, how sad that is.

50:07

In fact, if you go a little further and try this.

50:10

If I put a Boolean here also, and then of course, if I were to return,

50:14

let's say n mod 2 is equal to 0.

50:17

But before I do that print line, and I say e's even called, let's say far.

50:23

And I'm going to print the number for which it is called.

50:26

You can see that all that expands that we incur, which is not what you really want to do,

50:32

because that's not very efficient.

50:34

But before we go further, I want to mention one quick thing over here.

50:38

And that is, if you ask me, what is the real essence of functional programming?

50:43

And I'm going to say that functional programming is equal to,

50:48

and I'm going to add in this case, it is object, sorry,

50:52

it is, sorry, functional composition plus the use of,

50:57

so absolutely composition plus the use of lazy evaluation.

51:02

So in other words, if you ask me, what about object from the programming?

51:07

I'm going to say polymorphism is to, polymorphism is to,

51:14

or OP as lazy evaluation is to functional programming.

51:20

If you want to do OP, why would you bother if you don't have polymorphism?

51:24

In the same note, I would say lazy evaluation is asked critical for functional programming.

51:29

So when you look at this example, it did all the extra work for us to throw most of it out.

51:36

So I'm going to save this away here as from eager, eager to.

51:42

And what you can do though, you've got to be careful with this,

51:45

as you can go in and say, yes, I do want laziness and you put a sequence over here.

51:51

And when you turn that into a sequence, when you run the code,

51:55

you notice that in this case, you're not doing all that extra work.

51:59

You did not touch any value, pass the value six at this point.

52:04

So the sequence gives you laziness of evaluation.

52:08

And so you don't want to be running on a list directly if you have a very large collection.

52:14

And if you want lazy evaluation, you want rate on the sequence rather than running it on the list.

52:20

Because then it is going to evaluate lazily.

52:24

So using sequence as sequence in Cartlin gives you behavior like using streams in Java.

52:31

In Java, you don't have the filter and map on list.

52:34

You only have them on stream for a good reason because they want those to be done only one way,

52:39

which is lazy evaluation.

52:41

Cartlin gives you the choice, but you got to be careful what you're using,

52:44

otherwise you end up using the wrong stuff.

52:47

So from, you know, either revolution to lazy evaluation,

52:51

and so that becomes very efficient from the functional programming point of view.

52:56

So that gives you an idea about how we can use sequences to get laziness.

53:01

So with that said, Cartlin gives you a fairly decent amount of choice to do functional programming,

53:06

as much as other programming models.

53:08

You have to choose wisely and apply them.

53:11

If you're interested in downloading the code examples I showed you here,

53:14

you can download them from my website right here.

53:16

I just, as I wrote it, I saved it.

53:18

I'll zip it and post it in about 10 minutes from now.

53:21

You should be able to see it on my site after that.

53:23

And if you're interested deep into this further,

53:25

please take a look at programming Cartlin,

53:28

which is right now in better release.

53:30

It'll be released within a month or two in a production release after that.

53:35

So please take a look at that also.

53:37

Hope that was useful.

53:38

Thanks for coming.

00:00

Introduction to Functional Programming

01:00

Imperative vs Declarative Programming

04:40

Decoding Higher Order Functions

08:10

Understanding Lambda Expressions

15:52

Using Higher Order Functions and Parameters

18:00

Pass Through Lambdas Explained

20:35

Receiving and Assigning Lambdas

29:51

Understanding Filter and Its Usage

32:31

Understanding Filters in Functional Programming

33:18

Characteristics of the Filter Function

34:17

The Map Function Explained

45:47

Using FlatMap for One-to-Many Transformations

49:13

Understanding Functional Composition and Lazy Evaluation

50:40

The Importance of Lazy Evaluation in Functional Programming

51:55

Using Sequences for Efficient Processing

53:01

Choosing the Right Data Structures for Functional Programming

00:44

What advantages does functional programming offer over imperative programming?

04:23

How do higher order functions enhance coding in Kotlin?

08:18

Why are lambda expressions essential in functional programming?

16:01

How does the implicit parameter enhance function usage in Kotlin?

18:14

What are pass through lambdas and when should you use them?

31:31

Why is the filter function essential in functional programming?

32:46

What makes filtering values from a collection efficient in functional programming?

43:14

How does using map and flatten together simplify data processing?

46:37

Why is flatMap a powerful tool for transforming data collections?

50:40

What is the core principle behind functional programming's efficiency?

51:59

How does lazy evaluation prevent unnecessary computations?

52:31

Why are sequences preferred over lists for functional operations?


Declarative programmingIteratorSoftware developmentAlgorithmComputer scienceProblem solvingData structureKotlin (programming language)

Description

The content delves into the world of functional programming, a style that focuses on solving problems without changing the original data. This approach is contrasted with the imperative style, where both what and how are specified. Key concepts include immutability, where variables cannot be changed after their creation, and recursion, which involves breaking down complex problems into simpler ones. The speaker provides an example of calculating the total of double values for even numbers in a list, highlighting the complexities that arise with imperative programming. In this context, functional programming is introduced as a way to simplify code by avoiding mutable variables and loops. The presentation also touches upon the idea of composing functions to achieve desired results. By illustrating these concepts through practical examples, the speaker aims to demonstrate how functional programming can lead to more concise and maintainable code in Kotlin.