Let’s Get Lazy—The Real Power of Functional Programming - Venkat Subramaniam

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
good morning how many of you are lazy this morning alright that's good I'm in the right group excellent well I want to talk about getting lazy my name is Venkat Subramanyam thanks for coming we when we hear about come from programming we often hear people talk about immutability for example and various other things I won't even mention but I find that a lot of those things are really means to the end what we really are after is efficiency and coding well of course expressiveness of code is also very important in function programming uses that once we get familiar with function style programming but one of the real big benefits I think really is lazy evaluation so that's what I want to focus on today talk about how we can actually what is lazy evaluation and how we can actually benefit from that I'll give examples from a few different languages here I'll give a few examples in Java a few examples in c-sharp a little bit touch on Scala and just a little bit on Haskell as well so those are the four languages of touch on to various degrees depending on what we want to do best time to ask questions or make comments is when you have it so please don't wait till the end or hesitate any time is a great time questions comments anything you want to talk about drawing attention I'll be more than happy to listen to you as you've noticed already I don't use slides I hate using slides I'm going to just rant off you know answer questions if you have any writing code and just have some fun so let's get started so what does it really mean to be lazy what does lazy valuation really mean well lazy evaluation simply the first from the so called eager valuation so normally when a computation comes across system can decide to do it right away which is eager valuation or it can decide to postpone it well benefit of postponing it is we could do four things with a postponed operation first when you give me a computation I can do it right away which is eager of course or I can delay it to the point where I don't have to run it at all and of course both in life and computing efficiency comes from not doing stuff that we don't have to do so we postpone it until the point where we maybe don't have to evaluate this and we can just simply not evaluate an operation or we can pass an operation along to yet another entity which can decide to do whatever wants to do with it but of course we could then eventually evaluate it but minimally to get the results we want and not really execute it eagerly to the fullest extent well let's talk about that a little bit further but I want to talk about something else that we have in computer programming but a lot of us don't really experience it this is one of the moments for me over the past about thirty years I've been programming and that is I used to read a lot about stuff back in the 80s and I would like to dare and say wow this is amazing wish I could try this and it's it's it's excitement really to me today is I can actually try the stuff that I once were only able to read because of the you know so to say democratization of a programming world we got a lot of things available to us much more easily available without having to really go to a you know bigger corporation or a university to get access to things we can just have them available to us on our own laptops and devices well one of the things I want to talk about today is applicative versus normal order well most of us program in mainstream languages which only support unfortunately the so called applicative order normal order is actually quite abnormal in a lot of ways so let's talk about that with a little example to see what that really means in this context so let's take a little example to play with it so let's say we have a little function here let's keep it extremely simple I got a function called a compute and the function compute of course is going to take a number and let's keep it extremely simple returns as their double of the number but of course within this I'm going to simply say called so we can actually see that this function actually was called but of course I'm going to go back here and say int let's say x equals to 4 and then I say if X is greater than 5 and the compute of let's say 5 is greater than 10 then I want to go ahead and say for example in this case we'll simply output here let's call this as a result otherwise we'll say else really silly but we'll call this as no result so if you notice this we have a little code where if X is greater than 5 then I call compute and then of course I print out result or I print out note but when I round this code of course everybody in this room knows that when I run this code the compute method was absolutely not called well why was compute not called at all does anybody know the reason for it come on don't be shy thank you very much John McCarthy created this concept of charts of cuting way long time ago in the 1950s and everyone programming knows about shots of killing in fact that's kind of normal for us to expect executing there's no surprise at all we program knowing short screws securing very clearly on the other hand if I say temp is greater than 10 and I'm going to say int the temp equals compute well the question for you now is will compute B called yeah we said yes should compute be called no right so this is when you are feelings differ from what the language thinks it should do when you disagree with the language guess who wins the language of course right which is a sad part but of course in this case when you run the code it is going to go ahead and call the compute method there's no doubt about it and of course in this case the compute of course is going to return the value but sadly the compute was called even though you and I know very clearly the result of compute is not going to be used an example of eager evaluation but more so an applicative order but it doesn't have to be this way it is just this way in a lot of languages we use in the mainstream but let's take this example a little further just to play with it now let's take an example here in Haskell for a minute I'm going to create a function over here called add a and B equals a plus B and of course I'm going to call a function call evaluate let's say value equals value and then I say main equals and I'm going to print evaluate and then I'm going to call add over here and one and two now when I run this code of course what you can see is it printed three that's not the most interesting part in this code but let's talk about the order of evaluation here for a minute well in language like Java and c-sharp and a lot of mainstream languages when will ad be called well ad will be called right away when you see the ad being Val you know called over here the evaluation is instantaneous it's eager it's also known as applicative order so the word applicative order is just the order in which it is applied well ad is applied then evaluate is applied apply is a very fancy word for invoke are called so when ad is called it gets called are evaluated well but has color is very different in that regard in the terms of how it's going to do this stuff so most languages we use in mainstream use applicative order but some languages actually use normal order which is quite abnormal like I mentioned let's go to this example I want to show to you that ad is not being called right away ad is actually pretty evaluated pretty lazily so when you go to Haskell and say hey call ad Haskell says why because I want to pass it to evaluate so you need to call evaluate too and it says but why well I want to pass it to print okay that's a good reason because print is going to show the result humans will see it I better do this work so it's going to postpone until the point when it cannot postpone anymore but how do we prove it well unfortunately I cannot put a print statement in language like Haskell to prove it because print statements are impure operations Haskell wouldn't allow me to put it in arbitrary places so scratching my head you know how do we prove that this is how this works and I never thought I would actually use this debugger to make a point but that's exactly what I'm going to do here is to you know kind of step through the code so I'm going to go here and call G head C I which is the repple are interpretive evaluator for Haskell and I'm going to go ahead and load in this case the sample dot HS file well now that I've loaded it I'm going to put a breakpoint but I'm going to put a breakpoint right here on line number one character number sixteen as it turns out to be so I'm going to go back here and say break at 1 and 16 so I've entered a breakpoint now I'm going to go ahead and call the main function well you can see that the main has stopped right here on line number 1 and it tells you that it's waiting for you to continue and of course they continue right now and you can see the result of three well that proved the point that ad was actually called which is kind of pointless because of course we know the ad was called but what's really exciting is I'm going to go back to this code and change it to 42 now take a look at what this code is doing when I run the code of course the result was 42 but the beauty is you could have currently Haskell call the add function and have the face but why because I want to pass it to evaluate why are you calling evaluate because I want to send it to print well gosh then let's go ahead and call evaluate first you come in to evaluate you return to 42 you never actually use value then Oracle says yeah why bother then I'm not going to really spend my effort running the add method or add function because there is no value in running it well is that really true well to prove the point again I'm going to go back to the rectal I'm going to load up the function one more time the file so it's loaded up I put a breakpoint again exactly in the same line of code as we did a minute ago I'm going to go ahead and call the main function this time but notice it never hit the breakpoint it actually went right through and printed 42 a proof that ad was never actually evaluated well that's normal order right there as we saw so essentially Haskell says I don't have to be evaluating stuff unless otherwise I really need an evaluation this is a very normal sequence in language like Haskell but the first question of course obviously is why can't other languages like Java and c-sharp do this why does Haskell do this differently and the reason is actually extremely simple and the reason is in Haskell almost everything we create is pure so when we talk about immutability and purity and functional languages it's important for us to understand why purity is so important because if we don't understand that to me purity are immutability is like vegetables you don't go to children and say you have to eat vegetables nobody likes that so we got to give a good reason why this is important there's got to be a motivation to do it and the motivation as if a language does not guarantee purity of a function well it's got them eagerly evaluated languages like this is really funny when you really look at languages think about the false language like C sharp and Java fall on unsaved befalls languages like Haskell fall on save default by definition the default in languages like Java and c-sharp is mutability whereas by definition the default in language like Haskell is immutability so when you define a function in Haskell it is pure by definition and if you want it to be impure you have to plead with the language you got to say please please just as one function give me permission to make it impure whereas in language like Java and c-sharp you have to plead with the language to for purity because by default those languages promote immutability well because things are immutable if something is not being called when function can have side effects if the function is not called you're gonna get really surprised in languages in fact you may ask the question wait a minute if there is really true why doesn't see sharp and Java call the function when it starts of cuted but why do they call it when I sign to a temporary variable and the short answer to that question is language specs and language specs rule so in fact if you read the language spec for example C++ the language spec actually clearly says even if you are constructor word to perform a side-effect the language compiler may opt not to call your constructor so same way language specifications clearly say even if a function were to have a side-effect a shot securing will reject a function call and may not perform it but language specifications do not apply that rule in various other cases and that's the reason why the languages don't optimize so easily but let's take that a little further and see how this could actually be benefited with a few exceptions if you will understand that let's take this example we just saw here of the compute method but I'm going to write this example again here but in the case in Scala for a minute so I'm going to say over here define compute and in this case of course I'm going to say number given a number which is let's call this as integer if you will and then I'm going to simply say go ahead and say I print out let's say called and then of course return number times two just like I what I did in Java but in this case of course I'm going to say X equals four if X is greater than let's say five and compute off let's say five is greater than ten I want to print out let's say in this case a result and then of course print out else will simply say no result just example what I did in Java I'm just repeating that here in Scala well as you can see in this little example you saw the no result clearly compute was not actually called but what if I take this compute right here and assign it to a variable called attempt over here and then assign it to compute and then of course run the code well when I run this code of course what you see is unfortunately Scala called computer as well why because language like Scala and f-sharp are what I call as hybrid languages they promote immutability but they don't guarantee immutability at the language level so as a result they still have to evaluate things well how do we really get around that well Scala says you know you could have a side effect in compute I don't have a way to guarantee that and if I don't call it you're going to be surprised about it well you can have a little discussion with the language and say hey language compiler I know what I'm doing here so give me a little break here well that break comes from the word lazy if you will so I notice right now when I run the code Scala did not evaluate the compute method because I annotated the variable with the word lazy this is very similar to what you can do in F sharp as well you can give a little annotation to the language to say this one you can be lazy about it and even if it were to have a side-effect I'm not going to offended if you don't call it so the language says alright alright I leaves upon the eager eagerness I overhear and I'll postpone devaluation uncurl I cannot avoid the call do it but of course in this case as you can see if X we're greater than two and I run the code you can see that it actually called it because in this case the value of stamp is needed but if the value is let's say greater than five in this case you can see it bypass the call well that brings up the question gosh how do I do this in languages like Java and c-sharp short answer in Java good luck there is no way to do this well c-sharp makes it a little bit easier if you want to do something like that I'm going to just grab this function here from Java if you don't mind and bring it over here to C sharp so right here is the compute method and you know how to go from Java to c-sharp right just convert methods to uppercase you got almost the code you want well so here I have a code here in c-sharp the compute method takes a number and returns a double of that and of course in this case I want to print that out so we'll simply say here's the console.writeline I'm going to simply say call right here but I come back here and say int the temp is equal to four actually X equal to four and I'm going to say if X is greater than 5 and compute and I'm going to say this compute method takes a value let's say 5 is greater than 10 let's say and again I want to say result and of course else I want to simply say in this case no result well what does c-sharp do well clearly in this case you can see it said no result then he only called the method short securing at work but what if I were to take this one again but this time I'm going to say temp over here and I say temp is equal to compute 5 and you can see that C sharp is being eager just like Scala and Java were but in the case of c-sharp what you could do is again annotated by saying lazy in for example and you can of course define it as lazy but that brings up the question how do I really make things lazy in languages like Java and c-sharp well this is where a little bit of a charm comes in I'm not completed with the c-sharp code yet but I need one more minute before I can do that so come back to that so some languages are born lazy they were bought at the beach they were sitting there and doing absolutely nothing useful when they were born right so some languages are born lazy from the get-go but some languages have to work really hard to be lazy some languages are like me I'm always hyperactive trying to do stuff and my wife would tell me some days why don't you just sit down and relax I'm like how do you do that well that's the way some languages are they're just eager and you got to work a little extra hard if you want to make them lazy lazy so we talked about the ego versus lazy but how do you really bring lazy evaluation to some of these languages how do you postpone these evaluations well this is where the charm of lambda expressions come in so what do land expressions do well lambda expressions really are anonymous functions so you can create a function but one of the really nice things about creating functions as lambdas is you can pass functions around so a function can now receive other functions you can create functions within functions as lambdas and you can also return functions or lambdas from other functions to we of course call them as higher-order functions so what does this give us a benefit with the benefit you get out of this is now you can pass functions around but what's the benefit of passing functions around imagine I have a function I want to say here is a function I'm going to give it to you well what would you do when you receive something on your hand there are three things you could do you could use it right away if I were to give you an apple for example you were you could eat the Apple right away or you can't postpone be lazy about it and you can eat the apple later on you could throw it in your trash can and say I don't want to eat this half Apple all you could give it to somebody else and say here you go I got this Apple but I want to give it to you and that person in turn can do one of those four things give it to somebody else eat it discard it or you know eat it later so the point really is when we pass functions around we can either be lazy or eager or evaluated right now are discarded and so this gives an opportunity for us and that's exactly what languages like C sharp do so notice what I'm going to do here I'm going to send a new and I'm going to create a lazy over here so this becomes a lazy off end but I'm going to wrap this into a little lambda expression if you will and of course in this case you can see that I've just done a little bit of postponing in here and of course in this case I say temp dot value is greater than 10 and I'm going to evaluate it but notice the laziness in this case c-sharp did not evaluate the compute function why because a computer's wrapped into a lambda and the lambda doesn't have to be evaluated right away the lazy object says now thanks for giving this to me but I will wait until I see what happens now of course in this case if I say X is greater than 2 and run the code you can see that it did call it because the value was after all needed but when did this evaluation actually happen well to prove that if I say here over here you can see that here was actually called and then much later was the call the function evaluated that is the laziness of the evaluation as you can see so in other words we can use laziness to really make advantage of this if you're programming in Java unfortunately lazy is not available but nothing stops from creating one yourself if you want to and you would use a supplier to do this in language like Java the code at highlighted here in c-sharp is equal into what's called a supplier in Java and you can get to get get to use that pretty much to implement the same idea if you are interested in doing so we can see how laziness comes into picture right there but I want to take this further and say what can we benefit from when it comes to lazy evaluation and to understand that I want to take yet another example and play with it I'm going to use this example in Java but you could use that in any other language but a quick show of lands I could use either one how many of you program in Java here a few hands something a few in c-sharp I'm sorry well you know who wins here ok so we'll just use the c-sharp example in that case so I'm going to use I'll come back and show you another example of Java later later on but for now we'll use a c-sharp example so to prove a point here I want to this little example and I want to say in this case well what do we want to do let's say we start with a list of numbers to begin with so I'm going to say int over here we'll call it numbers equals and in this case I'll say new list of int again well in this case let's define a few numbers let's say 1 2 3 but notice I put a 5 and then a 4 change the order here intentionally and then I'm going to say 6 7 8 and this potentially could go on to a million values let's say it doesn't really matter but I want to say find the double of the first number greater than 3 and is even well I want to perform this operation so how would I do this in a language which is imperative in nature let's start with a little example I'm going to say result is equal to 0 to begin with I want to print the result you can pretty much do this example in Java much like what I show you here not very different at all so you can try it out in either of those languages so in this case of course I'm going to say far well for each of course I'm going to say bar and I'm going to say element and coming from in numbers and of course I want to loop through these numbers and get the result out of it but how do I get the result I'm going to say e is greater than 3 and E mar 2 is equal to 0 well then what do I do I'm going to say result is equal to element times 2 and do a break operation out of it well we all know what this style of programming is it's an imperative style of programming but imperative style of programming involves mutability often it also is very verbose it's something we have done up for a long time but it's tedious and it's a lot of work for us to do I'm going to also say that infrared Acela programming often has accidental complexity dig into it it's often error-prone as well I could do this a lot better in functional style of programming let's see how we can do that here in c-sharp so what I'm going to do in this example is repeat this but this time I'm going to say well numbers start and I'm going to say we're given a and I want to say he is greater than three and of course I could have really said he is greater than three I could have done that here but I'm going to instead call is greater than three as a function then I'm going to say where and I'm going to say is even a second function I want to call then I'm going to say a select and I'll call it as double it and then finally in this case I will simply say Oh what do I want to do the first number of course I'll call first right here and as for the result out of it well of course I need these little functions to make this work so let's get that going so public static boolean is greater than three well that should be fairly easy to do what does that do well takes a number but of course and all I'm going to do here is simply say return number is greater than three well let's go ahead and quickly write those other two functions I would need this of course is easy even and all that it is doing is mark two is equal to zero and finally this is going to become a double it and all that the double it function does is simply return back let's say number times two and returns the double of that particular number well when we run the little code you can see the result of that is also eight so that's a functional style code now clearly some of the benefits you see up here if you take this code and ask somebody what this code is doing what are they going to do they're going to have to look up and down in fact this is a beauty put us on you know imperative style code in front of somebody but then sit in front of them and watch their eyeball movement it does this right and it goes up and down up and down and then it does this that point is called the point of confusion because I like what does this code really do right now well the beauty of the code in the bottom is it's a single pass through the code given all the numbers that I have been given to me get me only the numbers greater than three now get me only their even numbers double them get the first one what a relief isn't it it's a single pass through you go from the top to the bottom the code begins to read like a problem statement our working with the company in the in the not part of the US and I don't know anything about what they do I was there to just do what training course I was offering but one of the developers said would you please take a look at my code and comment about it usually I get scared when people do that because when I can understand most of their code if it's not written very well but I look at the code and immediately was a release because well I could actually understand this code because the code was pretty much doing what you see up here it's got ships coming in it says what all the ships are we are dealing with we want only ships that are arriving and one from the international destination and one with this kind of cargo and I'm like going through the stop down and I'm reading through the code and I'm understanding it I'm like wow even I could understand your code what's up with this right and that's one of the benefits is that the code is actually easy to read easy to Express but that makes the question oh my gosh what about performance well be careful about this though if you're programming in language like Ruby are you know other languages this might not give you a good performance if you're not very careful about it but languages like C sharp and Java have done a really wonderful job this is why I really appreciate these languages they didn't just bring in the concept and say good luck with it they actually took the time to do a really good job with it let's see what that is in a second let's go back to this code here but I want to remind you about the sequence we are working with one two three five four so what is the number of effort units of work we do in the imperative code well let's take a look I got this collection on my hand he is one to begin with well one is greater than three no one two is greater than three no three is greater than three no five is greater than three yes of course he is five even well no is 4 greater than three yes is four even yes double four while that was eight computations we performed so the total cost of this was eight units of work that's what we did so eight units of work in the imperative code not all units the same but that's good enough for our purposes here so in the imperative style we did eight units of work let's look at this cord naively for a minute give it a collection of ten numbers I had to ask if every given number is greater than three that's what ten operations dead-on-arrival because ten already is greater than eight but to add add insult to injury then we take seven values and see if they are even ten plus seven seventeen computations then we double three of the values seventeen plus three four values of the one error well that's twenty-one computations while 21 units of work so this looks like 21 units of work compared to let's say 8 units of work but if you really wanted to make this worse just add a few more values to the end over here while the imprint of style code is sitting there and saying aha no worries your functional code is going to do a lot more work that doesn't look really that appealing isn't it well here comes the good news I forgot to mention one little thing about these kinds of functions and I've only seen these capability among my own children and functional style code they both are lazy to the bone in fact I'll give you a little scenario I've seen at my home a lot because that really doesn't it swell witness my wonderful wife often have to talk to my children while I'm away and I got teenagers well if you have teenagers you know what I'm talking about or if you have been a teenager once you wouldn't know what I'm talking about well teenagers are fundamentally lazy as you know so my wonderful wife will tell my teenage son hey turn off the TV it's like no words were spoken because nothing happens in the house and she clown looks at him it's like well I told him to turn on the TV nothing happened then she says go put the trash out and no muscle was actually moved then she says do your homework nothing really happened then she says I'm calling daddy and everything works well they could have renamed the first as called daddy that would have worked really well in my opinion or call mommy in families depend on the house but the point really is these are what are called terminal operations in other words when you go to the list and say where it says yeah okay thank you for asking me to do that but maybe I'll do it maybe I won't do it where again and let's select maybe first oh dear let me get to work because the resort is needed after all well let's see actually see if that's true sort of prove that I'm going to go back to this code right here and I'm going to go ahead and say outboard and I'm going to say e is greater than a GP called for width and let's go ahead and say zero here and then let's put number similarly I'm going to go ahead and output let's put YZ even right here and then of course finally you will call this as double it now before they run this code let's go back and see how this is going to be evaluated well this function does not let me tell you what it doesn't do it does not evaluate that particular function e is greater than three for all the elements in the list instead what it actually does is it takes three three and that's what's called C using it just pushes them together into one function if you will because it's all lazy functions and puts it together and says here we go and it runs that fuse to function for element but only to the extent how much it's needed so in other words it takes one and says hey 1 are you greater than 3 and 1 says oops not and it bails out gets out of there so does 2 & 3 well then comes along 5 and 5 says of course I'm greater than 3 but 5 escapes at this particular point 4 comes along 4 0 & 3 4 is even we double the four and first says Oh tanks and entire mechanism says oh we're done then no need to touch 6 and values after that and so when I run this code you can see the output exactly eight units of work one more time we evaluated 1 2 3 5 & 4 but we never ever touch 2 6 after all because that is lazy evaluation at work so lazy evaluation gives efficiency and code so even though this cord looked really expressive and beautiful we have often concern about performance but be rest assured with lazy evaluation we don't have to worry about it because it doesn't do the work until it no longer can avoid doing the work just because we have a functional style of code don't assume that this is available not all languages are created equal this is an example in c-sharp so is an example in Java if I create a very similar example you will see Java doing the same thing both Java and c-sharp also have embraced this efficiency you can again see the specification of being different here even if these functions were to have side-effect they may not be called after all well that brings up the point if you're interested in using functional style it's important for us to avoid side effects in our code in other words make functions pure because those functions may never get evaluated and we should be very careful about impurity of operations so all they'll talk about immutability and impurity have a really bigger end to it which is lazy evaluation and efficiency that we really are after so we can see the benefit of laziness here in this code as you can see and it decides not to evaluate this function until it no longer it can no longer can postpone it that's one of the biggest benefits you got out of it so that laziness gives us a benefit of having to really postpone operations if you will so as a result in this case you don't have to worry about running computations that don't have to be run that is one of the biggest benefits you get out of laziness lazy valuations has the performance implications but ok so we can have laziness and code that's great but can we benefit from laziness moving forward to a bigger degree and once this this is the beauty of things one thing leads to the next thing and generally speaking every single step may be really small but the minute you have taken five or six or seven steps and then you take a few more steps you certainly feel that you are indifferent slower than you were in and that's one of the biggest benefits is you keep adding on to these benefits so in the beginning we are saying Mitch your functions are pure well make sure you honor immutability mixture functions are pure makes your functions don't have side effect was what is the benefit that gives you several benefits just one of them being that you can have laziness but now that we can have laziness what's the benefit of that well one benefit is of course efficiency of code but there's yet another benefit and that is you can start bringing in evaluations which are you know related to infinite streams what is an infinite stream for this I'll give you an example here in Java but you can write an example in c-sharp as well I'll maybe convert this to c-sharp and show you in just a few minutes but what is what is infinite streams well an infinite stream absolutely has no bounds to it so I'm going to say stream dot e to rate and I'm going to say here is 1 comma given an element element plus 1 what does this do well it says this is Java example as you can see it says I'm going to start with 1 then I'm going to go to 2 3 4 5 and keep on going well how long can the stream go well there's absolutely no limit it's infinite in size I know what you're wondering you're saying if it's infinite in size what in the world would you store it on the cloud of course you're just kidding so the point really is it's infinite but how could you potentially have an infinite stream the answer is laziness so this lambda will not be evaluated until it really is needed and that is the beauty of lazy evaluation what laziness gives an ability for us to have things like infinite streams you can't tell it how many elements you want and it'll evaluated on demand when you actually ask for it and if you don't ask for it it's not going to do the work to get you that well what's the benefit of using something like this well let's go ahead and take a look at how we could benefit from this in terms of getting something really powerful and easy to work with well now you have a initial value and you have a generator that going to generate subsequent values for you and we can leverage on this idea really nicely well to understand this let's take a little example let's say given a number let's say N and the K while given numbers let's say N and K let's say compute the square root of the let's say first K even numbers are starting from let's say n what compute the total of square root of K even number starting from n well seems like a very simple problem to do compute the square root total of the square root of first K even numbers starting from n so let's go ahead and say compute and then I'll say N and K well what in the world is n let's give a random number 72 to begin with and I want to give another value for K which is another random number 219 let's say well I want to perform this operation and get the result out of it so how would I go about doing this work well I'm going to say in this case compute let's say double and we'll call compute n comma K and of course these are going to be simple values to pass in what what are we going to do well let's say in index is equal to n to begin with after all we need to work with an index value don't we well then I'm going to say count equal to 0 we are absolutely to count then I say double result is equal to 0 and then finally I'm going to return the result when we are done what did we do so far really no useful work after all right we all we did was we define some variables and it's a good time to take a coffee break and there was a lot of hard work right well the point is in imperative style code we create a lot of these things called garbage variables garbage variables are variables simply there to provide our code some some you know points to store data but we know they don't have a really good purpose at all in the code then I'm going to say wild count is less than K and what do you normally do it's a ritual isn't it you stop and asked the question he said less than or less than or equal to do you ever ask this question every single day isn't it in fact it's cold like this that makes us feel really stupid right because you look at that code and you say is it less than or less than or equal to you're trying really hard to reason it and then you leave the computer and we stop by the door what's real is van and you're eating food at Lund dinner and the family says are you ok yeah I'm fine you look really pensive no I'm thinking is it less than or less very equal to I forgot at work right it's always this thread that goes along you're not sure ever right these are code that's really hard to reason we have to think very carefully to know what this code really means then what do you do then you say well if it's even after all so I'm going to say if the index is mark two is equal to zero yeah we have a value that is even so what do I do now I'm going to say over here result plus equal to math dot square root and then of course I'm going to take the index value and compute the math out of it are we done well you're going to say no we're not done we need to increment the index value well okay so here is index plus plus are we done oh no not really you gotta increment the count value so count plus plus are we done what do you think is it correct no what's missing the plus plus has to be outside okay let's move it outside is it correct now you're like no no no one of them has to be inside one has to be outside well which one then well index has to be outside but count has to be inside is it correct now you're not sure anymore right that's the beauty of imperative style code you're never sure about it you're sitting there and picking deeply to reason it and then of course you're like I think it is correct right and you're trying to run through that and see what the result is to see what the performant what the code is going to provide as a as a response well of course in this case I'll mark it a static function and course it gave us some result but God knows if it's correct well but how do we do this code in more of a functional style well thanks to lazy evaluation and infinite stream let's see how this is going to become a lot easier to work with so I'm going to comment this code out but we implement it in a functional style so here we go so what are we going to do return stream dot eat r8 and I'm going to say iterate what am I going to do starting with the number N and then K while given an element element plus 1 there is your infinite stream that you have with you now what does the stream do I'm going to start with N and I'm going to keep on going n plus 1 n plus 2 n plus 3 and it keeps going well what's the next thing filter and what am I going to do with this filter well given an element I'm going to say element mark 2 is equal to 0 well give me only the even numbers well ok great what's my next operation map this value give an element return math dot square root of that value so we performed what we did on line 18 and line number 19 we took care of those two lines but then how do we go how much do we go limit toward K values is it less than K is it less than or equal to K it's K damn it keep moving you don't have to waste your time on it right and that's the beauty of this is simply you have this filter a map and of course limit and what's the last step we want to perform some operation and of course in this case I'm going to perform a sum and get the result out of this particular function so when I run this code of course it says I want the stream so let's go ahead and implement a stream right here bringing the stream dot stream so now that I have the stream on my hand what am I going to do now well run the code and you can see the difference not only is the code concise the code is extremely expressive as well as you can see right here so what's the benefit the benefit is you're not really dealing with accidental complexity in the code you're not sitting that in struggling with garbage variables you're not struggling with less than or less than equal to you're not dealing with control variables the court becomes extremely simple to deal with if you have the code in the top and you're looking at that code struggling to understand what the code is doing when a business analyst comes to you and says hey what does this go do your response normally is that's what I'm trying to figure out you shut up because you're really angry dealing with the code whereas in the code in the bottom well you can actually discuss with somebody and say that's what the code is doing does that really make sense to you because the code begins to resume of the problem statement but of course in this case lazy valuation plays a very vital role because without laziness absolutely you cannot do this so lazy evaluation is critical let's see how we can do this of course in Java well in c-sharp of course e sharp was influenced greatly by link so the functions don't look like filter and map but there are very equal and functions to do how would this look like in the case of c-sharp well let's take a look at that really quickly to see how we would probably some implement something like that potentially here so let's get this back to rolling well of course I want the map and the square root well before I do that really quickly here you could actually do a little bit of simplification here in Java as well using what I call the method references and that can minimize a little bit of noise in the code if you will just a few little benefits similarly if you had that other function available separately you could just use a method reference for it also well of course in this case I want the series to begin with but where in the world is the series I don't have one yet so let's go ahead and create it so public let's say in this case static I'm going to say i enumerable and then of course in this case I'm going to create an enumerator for the int itself and I'm going to call this as series if you will and what if the series do well I'm going to say account is equal to n whatever that value of n potentially could be so in this case I'll say a number is n that I want to start with then I could say wild true and then I could say yield the return and then in this case of course I could return count plus plus and I could start returning a number in the series if you will starting with this particular number or the value that I'm interested in returning well then of course once I do this I got a series on my hand I can start with the series but then I can say dark we're given a particular number I want to say number mod 2 is equal to zero and of course I'm accidentally to extract only the even numbers I don't care about anything else then I could do a select given a number again I can say math dot square root of that number and I can return a square root of that particular value and then finally of course I can say take and then give the value K that I'm interested in and of course this will start with the value and that we were supposed to start with so n is equal to you know whatever the value is my memory is so wonderfully flawed as you can see here while the value n is 72 over here so let's say 72 and then of course in K equals 219 that I wanted to use so we could say those are the values that I want to work with a little different here in c-sharp then we saw in Java but a series is creating with a yield word and it says I'm going to keep producing values along the way when you ask if and when you ask it and finally I perform at some operation on the result and print it so what we can do in this case of course is we could print out the result in the very end ask you to perform the computation so you can see that is a fairly simple equivalent of c-sharp code to do almost exactly what we did in the Java side and we got laziness in this case so what we're doing here is the take operation is kind of like the limit operation you saw on the Java side the take says only take K values out of this and not anymore well the evaluation of the innumerable is lazy as you can see it only performs on demand and it evaluates as many times as you ask you to take the value and no more so you can start benefiting from code like this and you can have laziness being you know come into picture so we can see how lazy evaluations lead to efficiency in code quite easily well the point I want to really summarize this width is that one of the really big charming features in functional programming if somebody comes to you and says what's really cool about functional programming or what would you really tell them as what is charming about function I'm sorry Oh obviously programming so when somebody says what is really big deal about object of programming is I'm going to say other from the programming is really all about polymorphism so isn't that true because what you really are after an Opie is polymorphism because if you don't have polymorphism because Palmas will gives you extensibility of code you can call a function but the actual function that will evaluate is not known to you at compile time at runtime it will decide what the function is based on the runtime type rather than compile time type so the most charming feature of programming is polymorphism there are good number of object on the programming languages that don't even have interfaces that don't even have inheritance but all of them have one thing in common which is polymorphism well what about encapsulation well encapsulation is extremely important what about abstraction oh my gosh that's extremely important but they really are after one thing encapsulation and abstraction really provide polymorphism to us with our encapsulation you cannot attain polymorphism opie so the real most charming feature of OB for me is really polymorphism so I am going to say a lazy evaluation so lazy evaluation is to function programming as polymorphism is to opie because that is what we really are after what are we really saying in functional programming oh you better really honor immutability you better write pure functions you better really honor all these wonderful things but often the question is why because what we really are after is efficiency that we get from a lazy evaluation so to me the real charm in programming is the efficiency we get from things like lazy evaluation of course parallelism is also possible and makes it easy with the mutability but of course things like you know parallelism and lazy evaluations won't be possible with our purity of functions but the real purpose of purity of functions is not because we want to be fancy about keeping functions pure it's not a fashionable thing the real reason why we go after those things is it leads to a greater good which is lazy valuations and potentially parallelism where it makes sense and that's what we really are after so that's really the charm in functional programming is efficiency through lazy evaluation I hope you will be eager to make use of laziness that's all I have hope that was useful thank you there is so the question and I'll repeat the question so the question is what about resources for you know in c-sharp honestly I had a really hard time getting my heads around functional programming and I I really finally decided to invest a lot of time in learning Haskell and I failed three times doing it and and then I realized the reason I found it so hard to learn Haskell was I was approaching it the wrong way I was getting really a you know wrapped around by and and and at the test the the sorry the type information and then I realized that Haskell actually is so wonderfully statically typed I don't have to really spend my time stay saying the type information so much but the point really is learning Haskell actually made me a lot better in writing functional code in multiple languages c-sharp you know Java and so on so the irony is I would say if you really want to get better write it you know take your time to learn Haskell and and I go out to learn about languages I would probably not even use at work and the reason I do that is because by learning those languages that I wouldn't use I actually end up using the languages I do have to use in a lot better way than I do so my recommendation actually is to go learn Haskell and the reason I say that is it takes you away from your comfort zone you're thinking about it in a completely different way because you're away from your comfort zone and then you end up actually using some design you know principles and patterns that you normally wouldn't and then when you come back to the language you are familiar with now you're thinking about it very differently then when we normally do in the constraints of the language as we do one of the biggest constraints I see often programming your language is I am constrained by what the language already provides and there are things that I can actually do in the language outside of what it provides in a very tactful way but I often don't even know that I could do that because you know the language has completely blinded me but when I go use a language which is completely different then I come and start tinkering with the language and say well I didn't realize I could actually do this so that's what I would say is go you know look at completely different things and then maybe that was really change the way you think about in programming language other questions are comments yes please start over the question okay yeah okay so sometimes a lazy evaluation can come also cause your headaches and the if you're a c-sharp programmer like resharper a few versions back said hey change everything to ienumerable and and then you know you can pass more things see methods and then and then immediately afterwards you start getting all these warnings saying whoa you may be in enumerated this innumerable two times and whilst whilst well you know we're dealing with things that aren't coming from a database or aren't coming from files you could but all of a sudden you know when that when enumerated that numerable is slow you've now gotten got yourself another problem right so so I that's a fair point and one of the things I want to really emphasize is it also tends out to be a lot more than syntax when we get into a language or a seasonal language the first thing we come across is a syntax right oh we're trying to understand all these constructs and how to put them together my argument is almost invariably we can have a really good command of the semantics of the language because we don't really take the time to understand the semantics and the implications of a particular thing we're working with a construct in the language we could a get infatuated with ideas which is not going to help us or get drawn into certain code not understanding the real implications offset and then we end up facing some of these challenges as well and so you know in fact a lot of ways it's no longer what you see is what you get right it's a lot more than what you see that you actually end up getting and and clearly that's a departure from the syntax because syntax often shows you what you are seeing and what you're getting well semantics is often what you don't see you know visibly in front of you and I think your question really in jizan hey take the time to really understand the semantics because semantics actually rules right syntax becomes your muscle memory after a while you're not thinking about the syntax after a while because it becomes your second nature to code with that syntax the semantics is something you have to specifically think about every single time because that's not something that you're going to see in front of you but that has a very strong reference to what you do so your point I would say yes you're absolutely right it's important to understand the semantics and then we can then say you know here are tools I have in front of me but the semantics tells me I shouldn't use this tool at this point maybe I should still go back and program in that imperative style in this case and that's the beauty in language like Java and c-sharp you have the control now to decide when to use which and I'm not suggesting functional is the right thing all the time or imperative is the right thing all the time I think we have to choose based on our current specific needs and and in for myself what I find out a lot of times is I don't know how to do the in functional style right now so I do this in imperative but three weeks from now somebody shows me a better way to do it in functional style and it's often not the way that I thought I should do in the first place but quite different from what I thought but the beauty is I can come back and refactor the code at the time to a bit much better style than I did so I absolutely I don't want to let go of the performance and efficiency and I can pick and choose what makes sense based on you know what what what I have at hand yeah one more probably question before we wrap this up oh all right well thanks for coming then appreciate it thank you [Applause]
Info
Channel: NDC Conferences
Views: 13,096
Rating: 4.9466667 out of 5
Keywords: functional programming, venkat subramaniam, ndc, ndc london
Id: ntWdmlrCheY
Channel Id: undefined
Length: 58min 13sec (3493 seconds)
Published: Mon Apr 17 2017
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.