Functional Programming with Java 8 by Venkat Subramaniam

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] alright welcome to being the session on programming in Java 8 my name is Venkat Subramanyam I'm going to talk about function programming in general for a little bit and then I'll draw example from Java 8 to see how Java 8 supports some of these Styles I'll also make certain distinctions as to a few things about functional style versus functional programming so let's get started well one of the really good things about Java is Java has evolved into supporting functional style of programming for a good about 20 plus years Java supported imperative style of programming along with object-oriented style of programming but now we can actually do functional style of programming also but why should we really care about this well functional programming has been around for a very long time it's been around for even longer than object-oriented programming has been around and one of the interesting things about function programming is it solves a certain number of problems that have just become imminent over the past decade or so so one of the things is the growth of computer applications we are seeing massive use of computer applications we can't have any human hack activity today that doesn't involve computer applications that was not the case of course a few decades ago and then of course when it comes to writing code there are two kinds of complexity that every one of us deal with one of them is inherent complexity inherent complexity is the complexity at the root of the application the domain and on the other hand a lot of things what we deal with is also known as the accidental complexity unfortunately though while we cannot get rid of the inherent complexity a lot of what we struggle with every single day is accidental complexity I'm going to make the claim that imperative style of programming is inherently complex what as functional programming has removed that accidental complexity from our shoulders that's one of the reasons why this is a better programming model for a lot of stuff we can do and of course with object-oriented programming one of the things we quickly run into is that it doesn't quite deal with mutable state a very well and shared mutable but it becomes really a problem and of course with emergence of multi-core processors we no longer are really dealing with multiple threads running on a single machine or a single processor multi-threading shears truly is multi-threaded where multiple threads can and run and of course a program that may pretend to work correctly on a single core may actually end up being broken on a multi-core processor so how do we manage some of these use well one of the biggest problems is mutable state well mutability is something almost everyone here has done and we don't feel really that bad about mutability so mutability is okay what about sharing well sharing is a good thing remember what mom told us to share so mutability is okay sharing is good but shared notability is devil's work the minute we bring shared mutability a lot of things can go wrong comes really hard one of them is it's a very highly error-prone code i remember day when a developer came to me and he said well this code over here is not working can you take a look at it to be fair it was not a very long piece of code and and I looked at it quickly and I said if you send this input it should give you this output is that I know right but it doesn't so we both were straighting staring at it like we are stupid and after a few minutes I said wait did you really mean to change the input given to this function on this line number seven he thought for a second and he said I'm stupid and he walked away well a lot of times we don't think about modifying variables it's really hard it becomes error-prone over time the code is really hard to reason as well we're struggling to really understand how this code actually works and to explain the code also becomes very difficult in other words the more state change we have in code the really hard it is to read a reason with that code and of course wait until somebody tells you to make that code concurrent and making such a code concurrent is incredibly difficult in fact one of the really big problems we deal with is the structure of the code is very different between being sequential and being concurrent and that really hurts us get performance out of code once we realize we have to make it concurrent well function programming solves a lot of these things but what is old is new again in fact some of the concepts of function programming really was introduced way back in 1929 1930s when the lambda calculus console was introduced of course the some of the first programming languages actually were functional in nature so this is not a newfangled idea invented yesterday it has been around for a very long time just waiting for the industry to grow up to make use of some of these ideas but one of the central concepts are functional programming is assignment less programming you may say wait a second are you out of your mind how could you program no assignments so I want to draw a parallel to this so we can get a better perspective on this so if you really look back in time back in the 60s and 70s maybe even into the 80s one of the things we really focused on is that four-letter word go-to so I'm going to say go-to is too structured programming and in in other words this is something we've been really hammered with is not to use go tooth let's entertain the thought just for a minute Here I am in Java code I'm going to go ahead and call a little thing called blah well very carefully notice what this says to us it says that error not a statement just keep that in mind blah is not a statement well I'm going to change this to go to well we know that go-to is evil we shouldn't use it good old Dijkstra told us gotas are evil don't use it so I'm using go-to here in Java but when I run it notice Java doesn't say not a statement instead Java says illegal start of expression what that mean well Java says go-to is a valid keyword but I dare you to use it so it's a forbidden keyword they don't want us to use the keyword okay that's great but I want to really go ahead and run this little code I'm going to take a very simple example here well we know that we cannot use go-to we shouldn't use go-to if somebody even suggest using go-to will frown on them all that is great but I'm going to go ahead and say far int I equal to zero I less than 10 and then I'm going to of course just do a very trivial simple loop here I plus plus in this case of course I'm going to say if I is greater than 5 then output the variable I so no big deal at all but this we know as structured programming it's structured program because we got nice structuring of the code we are stacking up the code one after the other and there is a good entry point there's a good exit point hey that's all really making sense that's basically what we would call a structured programming but what I'm going to do here though is I'm going to go to the command line and say Java P minus C and minus C is already an alias on my machine so I won't provide that and then I'm going to say classes right here and sample and let's take a look at the bytecode and what a surprise if you look at the bytecode being generated what do you see over there go to in the bytecode hey wait a minute did we say that in a structured program we shouldn't use go twos well go tools are like matches you I'm sure everyone here has matches at home we all use matches but you don't go to the kids and say kids I'm going to go take a shower here are some matches for you to play with well we use matches but matches are for adults to use not for children's to play with case in point go to is exactly the same so a structured program will have go to except that we will not have go to in our code there could be go to act layers below so in a very similar way when we say assignment less programming we're not saying there's no assignments period we are saying that just like we don't use go to we won't use assignments but just like assignments just like go to can happen under the hood assignments may happen under the hood as well so assignments are easy to assignment is to functional programming so this is a way to draw the distinction that go-to is the structured programming like assignments these two functional programming that is the evil part of the what we are trying to avoid like we try to avoid go to instructor programming we try to avoid assignments in a functional programming but a lot of times I use the word explicit assignment rather than assignment meaning we don't do assignments but it could happen under the hood in in layers below well the next thing is of course dealing with immutable state we don't want to be mutating the state instead we want to transform the state as much as you can and because transforming the state becomes a lot more easier to reason and work with than mutating the state but obviously one question remains Kyra's oh my gosh if you're going to be dealing with immutable state would you not base performance by copying objects over and over and over well let's think about something really in parallel here again version controls have been doing this for a long time when you deal with the version control you check in files the version controls don't make a full copy of the files obviously what they do is they make very nice smart copying where they keep the differences around so in other words we do smart copying rather than through copying or full copying in a similar way languages and tools and libraries can do this for us when we make a copy of an object it doesn't have to be a full copy it can be a very efficient copy a case in point is one example is tries where it rises a data structure quite widely used in languages like a closure and Scala where twice make a very smart copy of objects minimally on copy on-demand and that becomes really efficient likewise libraries can also be smart about how they handle data so they can minimize these garbage objects being created in between so there are ways to really save performance while achieving these goals as well but one of the most important things to think about is functions are considered as first-class citizens so what does that really mean functions are first class citizens well what it means is it's so far what we have done is we can't pass objects to functions well sure we can create a in this case objects within within functions and then finally of course we can't return objects from functions so we are used to doing these things for for a long time but what if we treat functions as first-class citizens we can start treating them and moving them around and passing them around so in other words these are called higher-order functions so what is a higher-order function well a higher-order function typically is going to take this idea that we talked about but in addition to doing the object composition we can also do function composition so if you look at the higher-order functions higher-order functions can pass functions to functions as well not just objects they can create fun functions within functions and of course they can also return function from functions as well so those become what are called higher-order functions that you can work with very effectively so we can do up decomposition or object decomposition but we can also do function decomposition as well but one of the most important things to keep in mind is that functions don't have side effects I want to emphasize that for a minute because it's easy to miss this a little bit so I want to emphasize that functions have to be pure well what does it mean to be pure meaning pure functions don't have side effects so side effects well what are side effects then well in this case there are two points we need to consider and I would argue that the first point is a lot easy for a lot of us but the second point is not that intuitive the first thing is a pure function does not change anything so we can all relate to that of course the function is modifying something well that's not pure but there's an important rule here does not depend on anything that changes as well so in other words a pure function should not make any changes but it shouldn't depend on anything that changes as well well the first rule I think is pretty clear to most of us it's quite obvious you don't want to mess with data you don't want to change share data that's obvious but if I say that a pure function should not depend on anything that changes we're like why well the reason is one of the critical features of functional programming is that functions can be lazy and if you're depending on something that changes outside your function cannot be lazily evaluated we'll see some of this later on when we look at some examples along the way so having said this what are really the benefits of this one of the biggest benefits is that it becomes easier to work with the code it reduces accidental complexity in code quite often that is one of the biggest benefits but I want to draw the distinction between functional style versus purely functional programming languages a purely functional programming language will not allow any mutability period a functional style language often suitability at the risk of we failing to do the right things so it puts a burden on you rather than protecting you but it provides higher-order functions so in other words you can say if the language provides higher-order functions it's a function of style language if a language goes to the extent of limiting mutability in addition to providing the functional the higher-order functions then it becomes a purely functional language for example Java and a lot of other languages are functional style languages like like Haskell for example is a purely functional language because they provide higher-order functions but they don't also permit mutability but what are some of the real benefits of this we're going to be looking at state transformation rather than state mutation so we take their data and transform through the states rather than mutating the state but let's look at what this really means to us in some context let's say before we go any further with this let's consider methods so what in the world is a method method it is a function after all which often belongs to a class or to an object so that's what we call as a method in Java a method is a function but but that function often belongs to either a class or it belongs to an object but on the other hand a function has four things well what are the four things a function typically has the first thing it has is the name of a function so we celebrated we give names for functions the second thing it contains often is a return type will we tell what this what is the function return the third thing is a parameter list and of course the last thing of course is the body of the function so that's what a function typically contains when we write them so let's look at an example of using a method or a function suppose I were to say thread is equal to new thread and then of course I'm going to say thread darts start over here and then I'm going to simply say in main over here and we can see that in main just popped up but of course I want to do something in another thread so we say new runnable over here and then once I create the runnable I'm going to say public void run and then with them does run method of course I'm going to say nyan another let's say a node or a thread so in this case of course we will run this function and we can see that in main popped up first and then an end of the thread once that kick thread kicked in it said that that's going to run but if you look at this code line number 16 he is a method which is the run method we lack that run method with unrunnable and then we pass it to the thread class we've been doing this for a very long time of course but imagine you are boarding an airplane and they tell you you can only take two items with you and you cannot take more than two items so what are the two items you're going to pick from here well what do you think is the most important item here the one you cannot board without obviously that will be the body of the function without the body of the function there's no point doing this well yeah you've selected one item you got only one more item you can select well obviously what good is having the body if you don't have the data to work with so you have to have the parameter looks to be given to you and that's it you're out of limits you can only take two things and that's exactly what lambda cans do lambda expressions essentially have only those two things it's got a parameter list first of all an arrow that separates the body from the parameter list that is the structure of a lambda expression so a lambda expression has minimal at the very minimum a parameter list and a body well what about the return type the return type is inferred based on the context here you don't have to say the return type what about the name of the method who cares when the work is done it's anonymous so lambda expressions are anonymous methods whose return pipes are inferred and all you carry with you is a parameter list an arrow and the body of the function so what I'm going to do here is take this example right here that worked a minute ago but I'm going to go ahead and rewrite this this time but this time I'm going to remove all the ceremony around it notice that's pure noise that I've highlighted so I remove that noise put a little arrow right there and then I'm going to remove the remaining noise from here and so we converted the code to use a lambda X version rather than using an anonymous function anonymous method anonymous class so in this case the thread is actually a constructor which is a higher-order function the thread says you don't have to pass an object to me of runnable it's okay if you pass a function to me which has no name and that function of course is the lambda expression that we are passing to this function so in this case you can see that we passed a function which takes no parameters and then of course the arrow and the body which is printing that message so we were able to pass this method so for the first time in a long time we've been able to treat the function as a first class citizen so what that means is it's kind of like we've been creating functions like they're kindergarteners the function comes to you this little code comes to you and says could I go to the neighborhood park please you said no sweetie you cannot go alone let me send an adult with you and we have been wrapping it now you can free that and you can send it away on its own so I've been creating functions as a first-class citizen now in Java 8 moving forward with the functional style of programming so what does leads us to is we can do some really powerful things with this let's quickly look at an example of how we can reap some of these benefits let's go to what we have been doing for a very long time which is a very traditional looping so I got a list of numbers 1 to 10 right here and what I want to do is loop through these so I could say for I equal to 0 I less than and the number star and then you pass and ask is it sizes that length is it count because obviously we can't have a standard isn't it if it's a array it's a length if it's a ArrayList it's a size go figure so then we could say plus plus and then we pass again as the question is it less than or less than or equal to because we are never sure about it and then of course to add insult to injury I got to say numbers again and do a get and get the data out of it well this is a very high ceremony but if you look at this code I'm going to argue this is a very complex code you may say wait a minute did you say complex isn't this a simple for loop oh no this is not a simple for loop it's a familiar for loop it's important not not to get confused with the terms the words simple and familiar are very different from each other this is not a simple for look it's a complex but familiar for look so what is familiar similar is something we have looked at several times we don't probably care to look at it again and something that we know very well and this is a very familiar for loop but I'm going to argue this is complex in fact it's very easy to prove it's complex because there is something already very simple we could say int element in numbers and then we could of course output the element right off the bat so you can see that while both of the code produce exactly the same result this one is a lot simpler than the previous one these two collectively are known as external iterators but we can use what's called an internal iterator instead so what we can do in here is we can do internal iterators moving forward and what that means is we can say rather than iterating through this this way we could simply say well numbers dot for each well let's stop right there and talk about this for a second notice in the earlier example we were passing the number too far and we know one thing about code structures like this they are never polymorphic on the other hand the minute you say numbers dot for each that you know is polymorphic because the implementation of for each can change depending on the runtime implementation of the collection you are dealing with so that's a benefit already that you are carrying with you but what we can do with this is you can now say for each and then you can say new consumer integer and then of course in this case I'm going to say public void except the integer value or element E and then we could output this element right there so in this case you can see the output is exactly the same as before we didn't have to use an external iterator we used an internal iterator now the benefit of this code is you are telling what to do and not how to do it you're focusing on what to do per iteration you're putting the iteration on autopilot and of course you can enjoy polymorphism all of these things are good good things but I know what you're thinking you're thinking if all that really good but to leave that benefit if I have to use yet another anonymous inner class heck no well sure but that's the beauty of this we don't have to we can take this one right away and say well rather than working so hard we can remove all the ceremony from here only keep the essence out of this and then we can remove the rest of the part as well and you can see the code still works right here so what we can do in this case is we can get rid of all that noise in the code these are called functional interfaces I always chuckle and I hear the word functional interface because I wonder if there are some interfaces that are functional what about the other points are they dysfunctional but in in essence it basically in this case where were a single abstract method interface is expected you are callable or enables the consumer in this case file filter anywhere a single abstract method interface is expected you can now pass of course lambda expression very easily that's what we just did but we can go a let's step further and improve this even further if you will now look at this code for a second we are saying here is a lambda given an integer I'm going to go ahead and print that integer but let's take a wild guess if you are iterating over a collection of the integers you put your hand into this collection and pick an element in your wildest imagination can you imagine what you would pick from a collection of integers a dog a monkey well of course it will be an integer so you know it's an integer the language knows it's an integer why bother seeing or the typist so for the first time in a long time Java is finally intelligent we can use very easily type inference with lambda expressions so you can simply leave out the type because the type is not adding any value in this case it is kind it is very obvious now make no mistake this is not dynamic typing this actually is static typing where the type is inferred at compile time just to verify that if I go back to this code and on the element II if I were to call foo notice the error message we are getting it says method foo variable e of type integer and so it very clearly knows that ease of integer there is absolutely no confusion in this point so we don't have to really specify the type in this case but we can go a step further again in this if you will now that we know that this is an integer we don't have to say the type well we can also get rid of that silly parentheses so if you only have exactly one element being given to your lambda you can get rid of that type the parenthesis as well so if you don't have any parameters you have to put a parenthesis if you have two or more parameters you have to put a parenthesis but if you just only have one you don't have to really specify that but one more improvement if you look at this code that we have at hand notice that in this case we receive an E and we print it and we could have done T plus 1 for example or we could have done e times 2 for example but the point is we didn't and all we are doing is receiving the data and simply passing it and this kind of lambda is extremely trivial in that it receives an argument a parameter and either passes it down to another function or invokes our method on it I've got a special name for these kinds of lambdas I've called these lambdas are as the office space pattern if you remember watching the office space movie hey Tom what do you do in this company I take the requirements of the program programmers and give it to from the manager from the business people and I give it to the programmers so all the tom was doing in this company was he was taking the requirements from the business people and giving to the programmers effectively really no purpose well when you have a lambda which is not doing really a lot other than simply transforming the data you are going to get tired writing this and you're going to say this code is stupid but history I shown one thing to us Java programmers never write stupid code they instead develop IDE is to vomit stupid code and people will be asking each other what should I do that you're using to do this well they know this was coming so they remove this duplication so if you notice we have a e over here so this ski is common so we'll remove it with this e right here and then we'll remove this arrow as well and we simply change this dock to double : and these are called method references method references make the code lock easier to understand and work with I'm going to say method references take a little bit more effort to write them when you get before you got used to them but method references often are easier to read so they are easier to read then right in the beginning but over time we get really better at it as we use it so what we did in this example is we took a external iterator the one that we had before and we refactored it a few times here is the traditional external iterator that we started with we got something simpler which is also an external iterator then of course we took the internal iterator which was verbose but showed us how we can do the looping and print stuff inside this loop and then finally of course we traded that with lambda expressions we got rid of the type and use the type inference we got rid of the parentheses after that and then of course eventually we use the method reference because this particular lambda was that simple so this gives you an idea about how we can go about using lambda expressions to start writing these kinds of code moving forward so this becomes a very fundamental shift in how we do this but one of the things to keep in mind is this is essentially a way of programming where we favor more of a decorative style of code than first and then a functional way of doing so what is decorated style a decorated style of coding is where you tell what to do and you let the underlying functions figure out how to do it in an imperative style of code you spend your time and if we're telling what to do and also how to do it let's look at one example of this to get a better feel for what that really means so here is a list of numbers 1 to 10 but let's say the given problem is find the total of double of even numbers so we were asked to find the total of even numbers you normally do to create this in the imperative style well first of all you would say result is equal to zero and when you are done you want to print out the result but then you say over here for int element coming from numbers and then you say if element here mark 2 is equal to 0 then of course you're going to say the result is equal to e times 2 but then you have to put a break out of it to break out of this loop well in this case of course well actually in this case we want to find the total of all the numbers so no break here so we got to make all these decisions and then we have to say plus equal to so you can run through it well in this case goes total of double of all the even numbers in the collection but we have written code like this for ever but if you look at this code anyone heroes with print code like this before well of course every one of us but the question is how do you feel when you write code like this dirty right really dirty in fact after day long work after writing this code you go home and the kids coming run come running towards you you say don't touch me I gotta go shove her first because this is very low-level coding we have to be doing over we can do this again but before we do this let's talk about two different things two different smells of imperative code the first smell is we got a variable we defined over here but we can we are mutating that variable over and over and over that's one of the smells of imperative style of coding is we do mutability quite often the second thing is you have to spend your effort telling not only what to do but also saying how to actually do this well on the other hand we can rewrite this code this time but I'm going to say output will start with numbers over here dart stream think of stream as an internal iterator and then we can say filter and I'm going to say given an element e return the elements only that are even and not any of the other elements so in this case we applied a filter we do a map given an element element times two and of course finally I'm going to say go ahead and give me a sum operation on the L results and return the result to me well if you look at this code both of those code produce exactly the same result but there is some really key difference between these two kinds of code the top code is of course imperative in nature we tell what to do and how to do and we also have mutability in the code if you look at the code in the bottom I'm going to say the code in the bottom is very humane no variable was tortured in the making of the result so we're not mutating any variables repeatedly the second thing is if you look at the code in the top you have to say every single detail you had to say get one element at a time please check is that element either even go ahead and double that element right here then fetch the current value of result then add to the value of result and then store it into the result you have to say every single thing this code is like talking to a toddler well the first time you talk to a toddler is very exciting you're going to say wow this was awesome talking to the toddler well the next thing you realize you got to say the same thing over and over you're going to say well walk slowly hold it with both hands look where you're going don't step on the cat on the way you're going to be having to say this and then you realize this is going to go on for the next 18 years that's called parenting isn't it well that's how it feels when you start writing code with imperative style on the other hand the functional style feels like you're talking to and responsible adult that is one of the biggest benefits you get out of this is a very nice way to transform so given a collection of numbers get me the collection which is only even numbers double the values and total so the code begins to read like a problem statement it removes the accidental complexity that usually is inherent in code that's one of the biggest benefits you get so what are some of the differences in the imperative style you focus on how to do things whereas in a decorative and functional style you focus on what to do mostly you encourage mutability in a imperative style you transform data in functional and decorative you often deal with side-effects when it comes to imperative style you write pure functions when it comes to a decorative and functional notice each of these functions are pure they don't change the word around them they are not dependent on anything that's mutable that's what these do along the way and of course you pass objects in this case you can pass functions as well and then finally the code is very hard to compose an imperative style because statements often cost mutability and you got to go back and get the data whereas functions nicely compose and you can transform data from one to the next to the next to the next but I want to deviate a little bit from this and talk back into functional style about lambdas and closures for just a minute so going back to this example let's take values 1 2 3 for a minute and in this case what I'm going to do is I'm going to ask for the values to be doubled first of all and print it so in this case I'm going to say numbers dart stream and then I'll say map given an element element times 2 and then for each I'm going to say system dot out and print illan while looking at this code for a second look at this line alone if you will here is a lambda if I ask you what 2 is 2 is a literal of course what in the world is e e is a parameter to the lambda much like args is a parameter to main e is a parameter to this lambda expression well this lambda is very self-contained it's happy it caught everything it needs not a problem on the other hand if I were to say factor over here well if you look at this code if I ask you what is e it's very clear what eat is e is the parameter to this lambda what in the world is this factor well the fact that of course is not defined within this lambda so this lambda has to look for this factor so this lambda well I'm going to put this down here so this lambda has to close over its defining scope so defining scope looking for the variable factor to bind to so in other words this lambda has to close over try saying the word close over really fast several times now you know what a closure is so a lambda does not have state so I'm going to say lambdas are stateless on the other hand what about a closure closure has the immutable state and so you want to make sure that it's actually immutable that's very critical so closures carrying a state with them lambdas are pretty stateless and so what a closure can do is a closure and capture a state where you are defining it and carried over to the point of execution waiting at this code but let's quickly take a look at this right here this lambda is defined right here in the main then you call the map method within the map method you could either call the lambda or you can pass the lambda down few more levels and you may call the lambda after that so in other words the lambda that's defined in the main may actually get executed at one or two or three levels from below the stack but when it's executed in that stack level below it needs a variable defined up here so that is where it captures the context from here and carries it down there for availability so that is basically what a closure s so one of the things we should keep in mind is closures carry state but it's important for us to make sure that the state that is carried by the closures are immutable now why is it so important that the closure states are immutable well to understand that let's go ahead and do this a little differently I'm going to go ahead and bring in the stream over here so I'm going to say scream dart scream and I'm going to say stream off the integer right here here and then is equal to numbers dot scream but I'm going to say dot map give an element I'm gonna say element x factor and then of course in this case I'm going to say that given the stream dot for each I'm going to go ahead and say system dot out and print Len and I'm going to go ahead and print the string well that's good so far but where is the factor I'm going to say in this case this factor is int factor is equal to 2 so the code actually in this case is taking the factor n and making a product out of it so that obviously worked but one thing to keep in mind is look at this closure for a minute well this closure definitely is not modifying any particular variable so that is good it satisfies the first rule of purity it doesn't change anything what about the second rule of purity remember the second rule of purity is it doesn't depend on anything that changes oh wait a minute it does depend on factor but one of the beautiful things about Java is that it treats these as what are called effectively final so in other words you could put the word final right here in this case if I say factor equals four notice you get an error right there on line 15 and it says you cannot change factor because its final but what if I remove this final from here well in old versions of Java until Java 7 you have to put final you have a local variable which is accessed from within an inner class Java 8 changes the rules just a little bit in Java 8 you don't have to put final now you may say wait a minute why don't have I have to put final well Java 8 says you and I have been going out for a long time we can trust each other just a little bit so as long as you know how to behave you don't have to go through the ceremony of putting final so as a result when I write this code this is called effectively final however if you come here and say factor equals 4 immediately Java screams and says I thought we had an understanding between us and you are now violating that contract this is why it's called effectively final in other words you cannot access a variable a local variable if you are mutating it well this is a good news this is when Java is trying to protect you in this case languages like Haskell are purely functional languages there is no assignment if you tried something very similar to this in c-sharp or javascript are a few other languages those languages will not stop you Java is trying to be protective here and says no no no don't do that that's not a good programming practice don't do that well that's a good idea so far but you know how some programmers are they will roll up their sleeves and say let me tell you how to really cheat Java these are very dangerous people usually but what you can do potentially in this case is because Java doesn't all of you to change factor you may get tempted to say in square bracket factor equals new int and then you could put a two right here at this point job is gonna say good luck and be quiet so when you run this code of course you got factor zero but if I go back here and say factor zero is equal to zero notice in this case Java will no longer complain Java will probably sit there and keep laughing and sale there's going to be fun watching these this code but in this case it won't protect you anymore this is also true if this was a member variable a field in your class Java is no longer going to protect however keep in mind this lambda disclosure is a bad closure because it's no longer pure why is it no longer pure because remember the two rules of purity a pure function should not change anything that's good but a pure function should not also depend on anything that changes well clearly this depends on something that changes in fact the reason this is really a terrible code is you can take this code make make a pinup photo of this and show it to different people and ask them what's going to be the output I - you're going to get different answers from the people and some of them will tell you well because two-factor 0 is - this is going to be the double of the values other people may say because factor is 0 now it's going to be 0 but which one is it the right answer is should we really be doing such programming because if you are trying to write code like this this is hard to reason error-prone very difficult to work this is also known as bad idea so don't do this so this is the reason why the purity of functions is so important we don't want to be messing with things like this we want to preserve the purity of closures that becomes extremely important so we shouldn't mix the impurity with these but this also illustrates the point about lazy evaluation so let's talk about lazy evaluation got an entire talk on lazy evaluation tomorrow but I'll simply merely scratch the surface right now notice that on line 13 we had a lambda expression sitting on line 13 that lambda expression on line 13 did not execute right now as you walk over line 13 during execution instead it waits until you come to line 17 and that's when that line 13 is executing that is lazy evaluation or deferred execution it says I don't need to be doing this now well functional programming cares a lot about this so I'm going to go ahead and say here if somebody comes to you and says are you a fan of object-oriented programming you say oh I love object of the programming well why do you care so much of an object into programming well don't get me wrong things like abstraction and encapsulation are extremely important but you're not programming an object-oriented system just for extract or encapsulation the real real power of object programming is polymorphism after all isn't it so polymorphism is - object-oriented programming so in other words this is what we really are after now we all can agree you cannot enjoy polymorphism without abstraction you cannot enjoy polymorphism without encapsulation but polymorphism is what we really are after an abstraction and encapsulation really makes it possible so polymorphism is to optical programming like and I'm going to say lazy evaluation evaluation is to [Music] evaluation is to functional programming of course if you're going to have lazy valuation you cannot have lazy evaluation without immutability that's exactly what we saw in this example because what is immutability do amiability says this function will not modify anything and it is not depending on anything that will change so you can run it now you can find it later or run never run it at all well if it is a impure function you are urgent to run it you're going to say run it fast run it now before the world changes and you're going to be in a hurry all the time and you ask the question when did this run did it run before the change or after the change you can completely defeat the purpose so you cannot be lazy without being having immutability and laziness is an extremely important thing because laziness leads to efficiency in code because you're not sitting there and making copies and copies of objects you can defer execution until a much later time and have those executed very nicely that's one of the biggest benefits you get out of this so to wrap this up one of the real powers in this is laziness but with laziness also comes this ability to what's called function pipelining our function composition function composition is a very powerful pattern we saw examples of this earlier but let's revisit this so suppose I had a collection of numbers with me let's say collection on numbers a collection of numbers 1 to 10 and I wanted this time say a get be a double of square root of let's say of even numbers well I can write this in a very nice flowing pattern so what I can do is I can say output but this time I can say numbers start stream and then I can say well filter give an element give me element mark 2 is equal to 0 then I can say dot map and Matt Squire root after I am interested in finding the square root of these and then of course this is going to be mapped to double this time and then finally I can say darts sum and then of course one so I totally I can simply return it well if you look at this code this time though what we have done in this case is we are saying given the collection of numbers get me only the even numbers but give me the square root of those even numbers and then find the sum of it and you can see how this begins to flow through this becomes what's called a function composition you'll go through transformations you take the collection you transform to even numbers to a map to double to performing the Sun well this is a function composition but the evaluation is also pretty lazy so what I mean by the evaluation is lazy is until you hit the sum operation these operations are not going to execute and then minimally they're going to execute whatever is necessary so the efficiency is big then furthermore in languages like Java one of the cool things about this is it is not taking a collection and creating an intermediate collection and then yet another intermediate collection it's not going to be doing that for you instead it's very efficient in knowing that these intermediate collections are really not needed first of all they're not available they're not visible outside so internally it doesn't waste performance by creating all those garbage collections internally it directly gets you to the result in the end so efficiency is big then it is really hard for it to be efficient without laziness as well in fact when the terminal operation some is called that's when it performs the operation and because of that it can be efficient it is not wasting its time and effort building all these intermediate results along the way that you get out of this so the benefits of doing this is first of all you get cold clarity when you look at the code you're not going back it's trying to figure out what this code is doing you're able to just loop the follow this code think about this for a minute if I give you a for loop with an if condition and a bake and I continue and I give you this code and ask you tell me what this code is doing and here's a challenge for you give an imperative code to somebody to ask them what does this go do and sit in front of them and what's their eyeball and their eyeball is going to do this it's going to start in the top look at the code and it's going to do this and then it does this that point is called quite a confusion right it's like I don't know what this code is doing but look at the functional code you go through a single pass through it given the collection get me all even numbers find the square root of them and total you're doing a single pass through it that becomes very clear to understand you also have fewer errors in code because a the code is doesn't have accidental complexity in it second reason why there are fewer errors is there is less mutability in code as well and that reduces errors also so less complexity less mutable favors a fewer errors in code it also removes all the extra garbage variables we have to carry around and so it becomes hard to reason you can remove that as well and finally the code becomes easier to paralyse as well if you are taking an imperative code with shared mutability and you tell them to make the code concurrent that's really hard because structure of the code changes a lot between sequential and concurrent on the other hand with this kind of code imagine this was a very fairly large collection what you can do is when you run the code you can see that it produces the result but you can simply throw a parallel in here and this will run in parallel and produce the result across the course either you can call parallel like this or you can turn this into a parallel stream as well but the beauty of this more important is the code structure is not different between sequential and parallel the chord structure for the first time in a long time is exactly the same between sequential and concurrent that's a huge benefit for us to enjoy and that is one of the biggest benefits tells us to summarize functional programming removes accidental complexity from our code well clearly we can all agree functional programming takes a lot more effort to understand the beginning that's because we're not familiar with it we are familiar with imperative style of programming but once they become familiar it takes us a lot less effort to write it removes these accidental complexity it makes it easier to reason the code it makes it easier to penalize the code so all that benefit we can enjoy that's one of the reasons why we want to favor this and it's really cool that most of the mainstream languages today are providing this including Java 8 if you're interested in downloading the code examples I showed you you're most welcome to download them at the link that's shown in the bottom hope that was useful thankful thanks for your time [Music]
Info
Channel: Devoxx
Views: 51,009
Rating: undefined out of 5
Keywords:
Id: 15X0qFtBqiQ
Channel Id: undefined
Length: 51min 39sec (3099 seconds)
Published: Tue Apr 11 2017
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.