Scenic City Summit 2016: Jeremy Fairbank - Functional Programming Basics in ES6 (JavaScript)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
all right well thank you for joining me good afternoon I hope you enjoyed lunch I'm going to talk about functional programming today in JavaScript we're going to utilize new es6 syntax use that to explore some functional concepts some of the basic things about functional programming and see how we can capitalize on some of these syntax and features to actually write cleaner functional code so my name is jeremy Fairbank a vlog at vlog up Jeremy Kirby calm and if you want follow me on Twitter I'm ill a Pocoyo and Jeff Emig on github just very briefly about me I work for a company called CG yet we're a completely remote team focused on design and front-end development and in addition to be an agency we have our own product called simply built which is a website builder and editor along with domain management and hosting so primary reason we're here today is because of libraries like these and this sort of Renaissance that's been happening at the JavaScript world over the past few years and it's functional programming has been showing up more and more and I think it's very important to understand why these libraries are problem my function becomes functional programming has becoming so important we have react and redux and some reactive things like rxjs making casts and lots of other libraries so today what we want to explore is what is functional programming what does that actually look like occurs for my screen and what would that feel like compared to procedural style programming object-oriented programming so the bigger question though is live fictional program why would it be important why would we want to utilize it incorporate it in our tool belt as programmers and so we're going to explore both of those things and see what it looks like why it might be useful to us so I want to start off just thinking about basic building blocks really think about this is functional programming the word function is in it and as you might think functions are to be our building blocks there are the atomic pieces that all of this hinges upon we're going to use just functions to build up very complex higher-order patterns to write very elegant and hopefully more error-free code so to start off what is a function really if we go back to elementary school math or middle school math we might have seen something like this where our teacher told us it's a unique mapping from the domain to arrangement we have two different sets and that might have been a little esoteric or confusing and then we might have gotten something a little more like this f of X equals x plus 2 and so that kind of clicked it's like okay this is just something that takes an input we do some computation and we produce an output we understand that if I pass in 2 I get 2 plus 2 equals 4 by pass in 3 3 plus 2 equals 5 and so forth but when we begin to look back at that earlier definition you see an important property about these functions especially in math our input those are our arguments that is the domain we have a set of numbers that can go in and then we have a guarantee that each of those inputs is going to map uniquely to some sort of output so that's the return value from a function that's our range of values so we see how those two things tie together and so there was this guy named Alonzo Church who kind of capitalized on this idea of modeling computation in terms of these pure functions and he was actually a professor of Allen Tariq's so while Alan Turing was developing these modes of computation based on the Turing machine Alonzo Church actually approached it from a different angle where we could express computation in terms of just small units of expressions called lambda expressions and so we developed what is called the lambda calculus and it's a turing-complete language itself and so we're going to build upon those very basic mathematical ideas of just representing computation from small units expressions lambdas functions to explore functional programming in the world of JavaScript so if I had to distill this down into some principles so we're like solid from the object-oriented world I would say we have four principles at least within the context of this discussion and so the first thing I would say about functional programming is that it's predictable and what that means is we have pure functions we have declarative style programming and that gives us certain guarantees where we have better determinism I have guarantees that since I have a pure function I know that if I pass this in I will always get back some exact output every time and so this gives a certain guarantees on predictability we also have safety this comes a lot from a mutable state in that I don't mutate state I keep you mutable city and if I need to change it and I'll just create a new state and that's going to protect me from slight typos and other errors that could crop up from beautiful state in addition to being safe state we also want it to be transparent so we want our state to be out in the open we want functions to compute on this data out in the open we don't want to stuff it behind objects that we just send messages to and so we'll explore that as well and then finally the idea of modularity and this goes back to the idea of functions as building blocks that we can take these small pieces and we can start piecing them together in different ways through things like creating partial application to below much higher order patterns and so it empowers us to deduplicate our code and have very modular code through functional programming now before we really dive into it let's go over some of the es6 syntax that we're going to utilize today in our code and just get a feel from how we're going to utilize it so the first thing we have our new variable bindings before we always have the var statement to declare our variables now we have let and Const and the difference from these with bars that they are block scopes so with var you know no matter where you place it it's going to get wasted up to the top of a function scope in this case with constant let they're just going to be inside block scopes and they're not going to leak out of that and then the slight difference between wet and Const is let is kind of like the new bar in that I can assign a value and I can always reassign it to a different value whereas Const is a constant binding doesn't mean the value itself is constant but the binding is constant which just means once I sign a value to it I cannot assign a different value to it to it later that would be a syntax error of course we're talking about functional program we've talked about lambdas which are anonymous functions and so we're going to have arrow functions which are one of the biggest things that came with es6 so with an arrow function we have again parameters and parentheses but now we separate the parameters and the function body with an arrow and then we can still have a normal looking function body we have our braces we have a return statement and so it's very similar to function declarations and function function expressions that we already have before we can also ask you a couple things such as the parentheses and the braces and in this case with this identity function if I leave out the braces that means that this function has a single expression as its body and it's implicitly returned so I don't have to explicitly put return x here and notice also if I have a single argument I can also leave out the parenthesis and just have X without parenthesis and so this is just a simple identity function to highlight how we can write very succeed simple looking arrow functions another thing we can add to our functions is utilizing the rest spread operator and it's the three dots ellipsis operator and when we use it in parameters it allows us to represent that this function takes a variable number of arguments in this case I have an array function it takes a variable number of elements and then I'm just going to rear atern those elements because they're going to get placed inside of an array when I use this rest operator so I call the Ray on one two three and I get back a literal array with one two and three in it I can also use this as a spread operator so in addition to gathering up variable number of arguments I can also pass variable number of arguments into function so I can just gather up my arguments here pass them back in to consult log so this is a nice cleaner way of doing the old method of calling the functions apply method where you could pass variable number of arguments in that way and that's something from earlier versions of JavaScript so here I can just pass in variable number hello scenic city summit and all those get passed in the console.log another thing that will utilize some is destructuring and if you are Python person a ruby person and I'm sure there are other languages that utilize this it's this idea that I could take a complex data structure like a list and array a tupple and I can pull out multiple values from it and put them in different variables so in this case I have an array of languages JavaScript Ruby Haskell and I can pull out individual elements by signing it to this Const with the Bracy braces j s and then using that rest operator again with a rest variable name and so what that basically does is it's saying take the first item which is javascript assign it to the Jas variable binding and then I use the rest operator and that saying take whatever else is left in the array and just stuff it in this rest variable and so that gives me Jas is JavaScript rest at the first index is Ruby rest at the second index is Haskell I can also use this in my function parameters so I can have a head function and it takes an array and its purpose is just to return the first element in the array well I could just utilize the structuring here and say pull out the first item go ahead and sign it to the binding X and then just return that X and so we'll see more examples of this later it's just sort of introducing you to what kind of es6 syntax we're going to utilize in our functional code the other thing which is widely available in a lot of other languages is default parameter values normally in JavaScript we would have to just check if the value has or if the parameter has a value because essentially all arguments can be optional in JavaScript functions and then we would have to assign later on with this we can declaratively say okay if there's nothing passed down at this argument position then go ahead and pre fill it with this default value so Greek here has a name argument and a greeting argument which we say has a default value of high so if I call greet with scenic city summit and hello then I'll get back hello scenic city summit because I've passed in both arguments but if I say greet with just Chattanooga I have not supplied value for greeting so it'll use the default value which is high and we'll just print out high chatting again one of the other things and this isn't necessarily a syntactical thing but it's just a new function available in es6 and you've probably seen something similar to this from lodash or underscore called a sign and it's on the object object in JavaScript and so what it basically allows us to do is just to merge multiple objects together whatever argument is at the first position will be mutated so typically we'll just pass in an empty object here and then what that allows us to do is pass in a variable number of other objects and just merge them all together and then give us back a final object that has all the keys and values from the other objects and whatever objects come last in that chain will override other values if they happen to have the same key and we'll use this later an example as well and then finally we have es6 classes we in fact won't use these in the functional code but we'll use it to contrast with some object-oriented code but I still want to make sure you're familiar with this es6 class syntax so it's basically just syntactical sugar for constructor functions from JavaScript there's nothing really special about them so this class point I can define a constructor method and it takes some arguments X Y and a science instance variables that's the same as just a constructor function called point and then that move by method on the Left that's the same as if I had just assigned a move by function to the points prototype and so we'll see this later and contrast it with some functional approaches so that covers some of the es6 syntax that we're going to see and we'll see them plenty more coming up in our examples as we look at the functional code so now returning back to our principles we want to first talk about predictability and we said in this predictability we have pure functions so we want to see what does that mean what does it mean to be a pure function and what's important about that so a very simple example is this add function takes x and y returns x plus y this is a pure function because all it does is it depends on its arguments and produce the value based on those arguments it does not have what we call side effects it does not depend on global state it does not you take global State it doesn't even print to standard out which we all so considered to be a side effect and what that gives us as a pure functions is this guarantee that every time I call add with two and three I always get back five and that's another property that we like to call referential transparency and that's just a fancy way of saying that I know every time I call this I get back five so in fact I could replace calls to this particular invocation with just the number five and it would not change the meaning of my program overall and so it's guaranteed that's wise what's so important about pure functions if they don't have side effects we know they produce the same thing every time then we have better better assurance that our program is correct so what then is impure we have this contrived example here of some functions of an API that depends on this global variable called name we're using a lab binding so it can be mutated it can be changed the value of it so each of these functions are impure get name is impure because it depends upon that global state if that global state changed which you can because of the set name function then we no longer have a guarantee that get name will always produce the same values therefore it's an impure function similarly like I said set name is impure because it mutates and changes that global state and then that bottom function print up or name let's impure for a couple reasons it depends upon the global state again we're printing out the name uppercase but it's also printing to the console which technically we would say is makes it impure because we could think of standard out it's just some more global state that we are affecting in our function so why does it really matter I mean is this that terrible to write impure functions like this I would say it can be a little harder to test it and that's what I think is so crucial about pure functions so if I wanted to test this particular API and test the print upper named function well first I need to make sure that I mock console.log so I can track calls to it and then I got to make sure I restore it after test so then I can print up a name I can check that console.log was called with uppercase Jeremy but notice that the functions I call my API are separate from the assertions I need to make so I have do more due diligence on my part as a programmer to remember I mutating some states and how I need to check that this particular function was called with this particular argument and so it's putting more burden on us and it's making it slightly harder to test now this is an easy easier example but you can imagine more complex examples with a secret of things how mocking can get pretty frustrating and annoying so one thing I like to say about this is that we have a lot of hidden state and that's uncertain state because we have to say set name print upper name we're doing all these mew mew mutating functions we have to remember that some state is changing behind the scenes and that can make it harder to test so what would be the remedy if we wrote it in a pure fashion testing suddenly becomes a lot easier so now I just write it upper named function it takes a name and it returns name dot to uppercase that's easy to test it's a pure function I know that if I pass in Jeremy I get back Jeremy uppercase if I pass in jet I get jet uppercase and so that's one of the beautiful things about writing pure functions and trying to do that as much as possible in our programs it's a whole lot easier to test we're just testing inputs and outputs so moving forward we talked about purity we also talked about when we have this predictable principle that we have declarative programming and understand declarative style program we need to first look at what is called imperative this is something we're probably already doing and it's this idea we we tell the computer how to achieve a particular result what does that look like so if I have this double numbers function takes an array of numbers and then it's going to produce a new array of numbers where every number has been doubled pretty simple so we'll create an array to hold all these values we'll do a for loop where we're incrementing some index variable push those into the new array where we double them and then we return it but we say this is an imperative style and if if not for the function names it might take us a second to read through the source code I know oh this function doubles numbers and you can see we're just giving a set of instructions to the computer it's not declaring what we're really doing here so what does it clear it it then well declarative is instead of saying how to do it we're saying what we need declare what our result we want and this is something you're probably already doing to whether you realize it or not if you do a lot of database queries sequel that's a declarative language you don't tell the database engine how to get the data set you just tell it what data set you want or if you're a front-end developer HTML that's declarative language you don't tell the browser how to paint it you tell it what to paint what you would like it to look like so how do we apply that then to JavaScript and functional programming well now we can like three lines we can do the double numbers with the native map method on the numbers array so we take the numbers we call numbers that map we pass in an arrow function and we can look at this pretty quickly even without a functioning and say oh in maps 2 n times 2 and we're mapping that for every item in the array that's a very declarative thing we don't know how maps implemented internally by v8 or SpiderMonkey but we know this is what we desire as our result and just to kind tie this back to what we discussed with the mathematical roots of this we can see that we're mapping from a certain domain a subset of 1 2 3 to a range subset of 2 4 6 so this is a very declarative style in it again it makes our our programs more predictable because we know they're pure we know that they are written in a declarative fashion we can reason about them better so now moving on let's go to state we talked about the principle of safety and that was immutable state and the idea is we don't want a mutator state we don't want to change properties on objects we don't want to change items in an array instead we would prefer just to create a new state if we need to change it don't mutate what we have because that could lead to subtle bugs and issues in our programs look here's an example very contrived example let's say I have an array of hobbies programming reading music and then let's say I want to grab the first two out of that I want to log them out it gives me programming and reading that's fine and then later on I want to print out again what was in the hobbies array originally now I'm getting back just music so what was the problem here well in this case I just had a slight typo but I had a mutable state I used the splice method accidentally instead of the slice method in JavaScript which normally just gives you a copy new array with the value indices that you specify splice is similar but it will mutate it will change the original array and just cut out those values from the original array so this is an instance very contrived of where subtle issues can happen in our programs and we're mutability can trip us up and we don't realize it so there's a couple things we can do to alleviate this back in es5 object up freeze was introduced which is a function that allows us to as the name suggests freeze an object or an array prevent it from being mutated so that's a nice approach to utilize and we'll see that a second another approach that I highly recommend is immutable j/s which is a library from Facebook and it has a lot of immutable data structures that you can utilize don't we wanted to apply just the object freeze all we need to do is call object uh freeze on our Ray and now when we mess up and we miss type slice we put splice it's going to throw a type error so at the very least we're going to get an error to say hey you may not meant to do this because you have a mutable state and you don't want to mutate it and so hopefully we can catch this bug earlier because of that so immutability can give us this these sort of safety guarantees to a certain extent and help us out a lot in our programs so another thing as we talk about safety we talked about also transparency we want our state to be transparent we want it to be out in the open and what that means is if we think of object-oriented styles of programming where we we stuff our state behind an object we send it messages we mutate that state but as we saw earlier with some of our testing code samples it can get harder for us to reason about what's happening in our program we have to remember how these things mutate our internal state so we're turning back to that point class this is classic example we set a point at the origin and then we want to move it by certain DX and dy but it's all mutating something underneath and that can be harder to reason about like I mentioned and not to mention when we deal with mutable state we might run into certain bugs that we didn't anticipate in our programs so how do we approach this name of functional programming that is to just expose our state don't mutate it keep it out in the open and have explicit flow of data so now instead of using a class let's just have a create point function it takes the X and y but let's just represent it our coordinates as an array of two items kind of like a double and we'll also freeze it to keep it immutable to make sure we don't accidentally youtaite it and now when we want to move the point we won't change the values in that array will actually produce a new array so move point by notice we're going to use that destructuring syntax that I used earlier so when I pass in the point I'll go ahead and D stretch the array back out to the X&Y coordinates I'll also take the DX is dy and then I can add those create a new array freeze it again and now when I create the point if I want to move it well I just need to go ahead and create a new point you keep that state more out in the open and have this explicit flow of data where instead of mutating stuff underneath we just have functions that operate on data and produce new data and so this can give us other guarantees on how our data is flowing through our programs and we're not hiding as much behind objects so looking at immutability the safety guarantees transparency there are definitely pros and cons so we've mentioned some of these pros we have safety we saw with the hobbies example where we can maybe catch bugs earlier because we're using a mutable state if you have user heard of Redux one huge benefit of it is that it forces you to always produce new state in your applications and so if you use Redux dev tools or something like that you basically get free undo redo logs for free and that's really nice because since it doesn't let you mutate your state you just create new State you can hold on to that old state and that makes it easier to debug your programs if you need to go back in time essentially we saw we have an explicit flow of data too so we can reason about what's going on in our programs a little easier and then I have a couple points there which are caveated we say less memory usage you will see what that means in the next slide but we also say we have some concurrent concurrency safety now javascript single threaded but we can still run into race conditions if we have potential multiple AC actions out on the out on the wire and maybe they're going to affect some shared state if they don't change the state in a certain order that we expect then we can still run into race conditions but if our state's immutable and we don't want to mutate it then we don't have to worry about this so we have concurrency safety already now some of the cons which all met there is a little more verbosity we're bringing our state out in the open we're not hiding it behind objects we don't have these always nice clean interfaces where we just call some method and we know the state that's hidden gets changed if we're creating new objects then that also means there's potential for more garbage collection and actually there's potential for more memory usage which is at odds from what I said earlier these are caveated as well especially if you use a library like immutable j/s if you use something like immutable j/s it's smart enough to when you create new objects to know how to sometimes share the underlying data between two objects because it's immutable you can share that data you don't have to worry about something mutating it and breaking it and we won't have time in this talk to really dive into immutable j/s but if you're curious about functional programming I highly recommend checking it out utilizing it so now we've talked about state we've talked about things like purity and declarative style programming so now that we have some of that foundation underway let's start looking just at functions and how we can see important properties of functions in JavaScript and especially in functional languages that empower us to do some really cool modular style programming and just treating these as small atomic pieces so this first thing we'll talk about it's pretty much a given whether we realize it or not is that this idea of first-class functions javascript has functions as first-class citizens so what does that mean when I do this Kant's multiply equals some anonymous function the fact that I can assign a function to a variable is actually a very powerful concept whether we realize it or not this means it's a first-class citizen in our language no different than a boolean string a number because I can assign those availables I can pass them as arguments I can take a function declaration I can alias it to some other variable binding and like I mentioned we can pass in functions as arguments and we've probably been doing this for a long time especially if we're JavaScript programmers but it's it's nice sometimes to sit back and think about wow this is actually very powerful and a very useful thing many languages years ago didn't have something like this and it's very empowering to have it within our repertoire so we can build upon that especially in JavaScript and utilize what's called closures and you've probably heard of this but it allows us to encapsulate certain state and that's what we're going to need when we want to start looking at in a few minutes partial application currying and composing functions which allow us to do this building up to higher-order patterns from very small small pieces so what is a closure if I take my add function from before and now I'm going to separate out the arguments I'm going to create this create adder function and notice all it does is it takes an X argument but now it's going to return a new function again I can return a function because it's a first-class citizen when you in fact would say that this create adder function is a higher-order function because it it returns a function as a value so I return this new function it takes a Y as argument and then inside we finally do our computation X plus y so we can kind of delay on computation but we can use this as a small building block to build other functions without explicitly writing them so I can create a function that adds 3 to whatever's passed in just by calling create adder with 3 I'm essentially filling in X to be 3 and notice inside that second function when I when I invoke that at the bottom I'm referring to that X that was passed in earlier that's a closure I'm closing over that X reference right there in that later function it's able to remember what that value is and utilize it and that's a very critical concept that we'll utilize as we keep building on these foundational patterns so what's a more practical example of this for example to look at let's say we have a request function and that's just responsible for wrapping over the fetch API which is essentially a nicer way of doing xhr calls to you know our API endpoints so I can call a couple API endpoints but let's say I have these custom headers I always need to send up to my API well I could get slightly repetitive so of course I could just write a function that always passes those headers up but we would like for this to be more general purpose ideally so what approach we could do and I will caveat that technically this function is impure but what we could do is we could take that same concept we did with create adder we could take options as an argument and then we can return another function that will take other options and then we'll finally call the original request function and we'll use object to object assigned to merge all those in so all that is is a fancy way of saying I want to go ahead and pre-fill some defaults some shared options in this case my custom header that I want to use and that reduces that duplication so that's one benefit of using closures we can reduce some of the snoop occation and then I can just invoke my different API s with their URLs so there we take the options and we can refer to it inside that inner function so these first class closures they are going to be this foundation for these higher-order patterns that we're going to start diving into now and looking at so the first thing is partial application and what partial application is going to do is we can ask the question say well you know I have this create adder have this create requester and I can keep doing this pattern over and over and over and it's going to get a little tedious so what if we could have some more general-purpose way to essentially fill in those X so fill in that options and that's one thing we can do with partial application so we could return the same add is just a function that takes X and y it turns X plus y and then let's say we have this hypothetical function called partial we can pass in add to it again because these are first-class citizens in our language and then I can pass in 3 and what I'm saying is take this function whatever its first argument is let it be 3 pre fill it with 3 and that gives me back this add 3 function that when I invoke it all it needs to do now is fill in its argument with Y and then I can return the result same thing with the request function we could do the same thing if we had this hypothetical partial function I could call it on my request function and now what I'll do is I'll have it take two arguments a defaults and options and then we'll just merge those with object sign but I can use partial to pre-fill in those defaults whatever shared options I need my custom headers in this example so how would we implement this partial function that we keep talking about it's actually very simple to implement with es6 and also if you are big Moe - or underscore fan partial is also available in those languages if you don't want to implement it yourself but we can take two different approaches to it the first approach is we can actually utilize something that's already natively available in JavaScript if you've heard of the bind method on functions what it normally does is it allows you to bind the this context in JavaScript and if you've done JavaScript for quite a while you have probably run into issues with this so you can use that to just say set the this special variable to a certain context one not very well known thing about bind though is any number of extra arguments you pass into it can actually be partially applied arguments so it essentially does what we just saw in those previous slides with the hypothetical partial function so what I can do is I can just capitalize on this we're not worried about this where functional programmers we don't want to use this so we'll just pass in null for that first argument and then we'll use the spread rest operator here to just pull in all the variable number of arguments that we want to partially apply into this function and just pre-fill their values now if we wanted to handwrite it all ourself it's not that much more complex we just utilize the rest spread operator a little more so again we take a variable number of arguments after our function we return another function that takes in additional arguments again variable number so we'll use the rest operator and then finally we can invoke the original function we can do that it's a closure so we're referring to it when we originally passed it in and then we just make sure to pass in first all those pre filled arguments the ARBs variable and then pass in the other arms that we just passed in and so that allows us to accomplish our own partial function in pure JavaScript so now let's take that concept a little further what would be really nice is if actually we didn't even need to call partial on some function it would be nice if our functions just sort of had this concept built into them already where they could partially apply on their own we don't have to manually do that and that's what we call currying so there's that subtle difference so what that means is with currying what I do here see is I call ad I only pass in three and that's going to go ahead and pre-fill X to be three so what this is smart enough to know is that you haven't given me all of the arguments yet so I'm just going to go ahead and fill in what you have given me until I have all of my arguments satisfied and that's what happens when I then evoke add three with two and get back five I could apply the same concept again to our request function pre-fill any default shared argument such as the headers and then invoke it again with our API endpoints so how do we accomplish currying with JavaScript in es6 well little secret we already did earlier with the create adder function only thing is I wrote it differently what we're doing now is we're just writing it in one line using the arrow functions and just using that single expression body at least for this add function so notice here we have two arrows now maybe a little confusing but let's just take it from left to right so first add takes the X so what we saw earlier with create adder and it returns a new function that takes a wide we've just alighted the braces this time and we put it all on one line so we take the Y and then we have another arrow which maps them to X plus y so the basic general rule of thumb you could think of this is that instead of using commas to separate our arguments we'll just separate them with arrows and that essentially gives us a rudimentary curried function and then at the bottom just so you kind of see what's happening there's the old es side version of this function where we just declare a function add and then we'll see where we return anonymous function but takes a Y same thing with the request function that we've been using in our examples separate our arguments with the arrows and that gives us this nice curried function where we can just build in partial application automatically so it's really powerful wonderful concept so this is all well a good nice interesting topics but is it practical is it useful how could we really use this in real code so let's actually piece this together and see a not a not unrealistic example how this might be useful and how we could take small building blocks to solve a slightly harder problem so I have this contrived example where we're going to basically query a API for shopping cart and whatever items are in the cart and what do I do is I just want to take the price of each item apply a discount and apply the tax rate to it we're just going to use curried functions and promises to accomplish this so the first thing is we're going to write a map function and what we're going to do is make it a curried function its first argument will be the function that we want to eventually apply to an array of items the second argument will be the actual array and then we'll just delegate to the original array map implementation remember we saw that earlier when we wanted to double numbers we've color a map we passing that function that map's in to n times 2 or just making this more general purpose here where we can give it any arbitrary function to use we'll have a multiply function that's just like our add function we're just doing multiplication this time we're going to have this function and essentially what that does this is actually a function in low - - that does the same thing but we're going to take in them key stream as the first argument second argument would be an object and what we want to accomplish is just basically pull out whatever value exists at that particular key for that object and so now here's how we can start utilizing these curried functions instead of writing a discount function instead of writing a tax function I'm just going to use my multiplied function because I can express the discount I can express the tax rate in terms of multiplication if I want to apply a 2% discount then I'll just multiply by 0.98 that'll decrease by the two percent of the original price same thing with the tax rate if I want a nine and a quarter percent tax rate I'll just multiply by one point zero nine two five so the curried function so all I've done is I've filled in X it's still waiting on that Y which will be the price that we'll get eventually already seen this we're using our courage request function to fill in our custom headers then finally we'll make our API request and then we're going to look at that a little more closer but see how we're utilizing everything up top there to handle a lot of complex stuff down there on the bottom so what we're essentially doing here is we make this request we're using promises it's going to eventually resolve we're going to get back this response an array with three items the prices are five ten and three dollars and then we're going to use attach the then callbacks for the promise and we're going to pass in functions to operate on this data but look how essentially more declarative this can be we can read this and say okay when I get this response I know I want to pluck out the price I want to map in the discount and I want to map in the tax rate so taking those a step at a time remember pluck price curried function we give it a key gives us back a function that expects an object so we still have a function map expects a function so we give map that particular function that's going to plug out the price and then once the promise resolves the map function is going to finally supply the array and it's going to map that plunk function over every item in the array so there we can pull out five ten and three next it's going to send down that array of prices to map discount again discount we created by just invoking multiply once with the discounted rate and then maps going to apply that to every item and similarly with our tax rate we'll make sure that we can just apply it all at once and so this gives us a very definitely interesting way to do a lot of this complex stuff with very small building blocks that we just use curried functions to express this in a very pure and declarative manner now one final thing we can do with this though is talk about composing closures composing functions together building upon create functions and if you've heard of this you may remember again back to math when you compose functions say you had f of X and a DX and you compose them you produce some sort of F of G of X or G of f of X the basic idea is especially if maybe you've done some UNIX shell programming or something this idea of piping one thing to the other where you have something that takes an input it produces an output its output becomes the input to something else so you're just chaining these together and you're passing data down the pipeline and that's essentially what composing functions is so if I had something like this process word and we're going to use some we won't show the implementation of these functions but we have - a traverse to uppercase they're fairly self-explanatory reverse will reverse the string - AIT's going to put a - in the middle as best as possible but I want to say apply all these functions at once so what I could do is I could compose them together take all the functions chain them together to where it becomes one new function that applies all of these one at a time and by convention normally with compose we would go from right to left now we'll mention again compose this is not something built into JavaScript so this is another hypothetical function but it's available in low - and underscore and there's actually a different version called flow which is basically doesn't left to right instead and this can be implemented as well I don't have time to show the implementation of this but the slides online will have a basic example of how you could write it yourself if you're interested but see what I can do here is I can chain them together and then I can again map over these this array of words and apply each function one at a time to each item I don't have to call it on my own it just chain together for one function and just to show you what that kind of looks like explicitly is if I wrote it explicitly down there on the bottom it's essentially as if I'd call to uppercase with word and then just let that get passed into reverse and whatever that produces get passed into hyphenate but we've just made this a general-purpose approach where we can compose them together and do it in a more declared a fashion so how is this useful how could we utilize it well I should let's go back to our example we just saw earlier with the shopping cart notice here what we had done it mapped over the array three times so sorry about that so we had basically we iterated three times and in this case that's not a big deal we had three items in our way but if we have something that's more performant intensive maybe we're operating a lot of data we may not want to iterate three times transforming all these items in the array so what we could actually do is just add composition to the mix here so now we can make this a single iteration remember map just needs a function so I could produce a new function where I take plucking the price out applying the discount applying the tax rate all compose together that gives me one function that does it all together and then give that to map and that ensures that we can apply all these functions in one iteration instead of three iterations so this can be very useful to just apply multiple things at once to array of items for example so we've done a lot with functions we've talked a lot about state and mobility one thing we haven't quite covered especially when we think back to imperative style programming is how to deal with the loop issue sometimes we have problems that we have to use a loop to solve it and we've already said that loops those are imperative we use mutable state and it's not something we necessarily desire to do in functional programming so how do we tackle this particular issue in functional programming well this is where we would incorporate recursion and you maybe use recursion before especially if you're doing a lot of graph traversal type problems and whatnot but it's a very powerful and declarative way to solve these type of loop issues in functional programming and we essentially just want to solve a problem in terms of itself so a classic example of this if we go back to that is the factorial remember with factorial we have a number and exclamation point in this case for exclamation-point factorial 4 times 3 times 2 times 1 that gives us 24 and in general we would say that we have n factorial would be n times n minus 1 times n minus 2 and so on until we get down to one again so if we wanted to solve this in JavaScript we might take the imperative approach we said okay well this looks like I need a loop so we could start an initial result value of 1 we do a while loop where we multiply like the result by whatever in is passed into the factorial and we just decrement it we keep looping until we reach the end of the loop and that works fine but we don't want to do this in functional programming we want a slightly more declarative approach so instead we could do this in a recursive manner where you can write actually fewer lines of code and we can actually express the problem closer to its original mathematical definition even so notice here factorial ends up calling itself and notice it actually models that general representation of factorial that I mentioned earlier in times n minus 1 times n minus 2 and etc except here notice we have n times factorial of n minus one so it's essentially going to keep calling this recursive function over and over doing the N minus one n minus two and etc but eventually we need to stop or we're going to get an infinite loop and that's where we have what's called a base case in recursive functions in this particular instance we know we're going to stop at one so we're going to check whenever n is less than two go ahead and return one and that'll know the answer to start bubbling back up and give us the final answer to the original call so if we did this as factorial four remember this is going to make a recursive call n times factorial of n minus one so that's four times factorial three and that will in turn call factorial 2 factorial 1 and now we've reached that base case remember n is less than two so now we can return the 1 and then we'll just start bubbling up the answer two times 1 3 times 2 and then 4 times 6 that's how we can solve it in a very declarative cursive manner and this is a general approach you can apply to a lot of problems and there's just a couple steps if you have a math background you did maybe a lot of inductive proofs back in the day it's very similar that you need to find what's called a recurrence kind of ties in with that word cursive what patterns you need to repeat this is also very important in dynamic programming if you've done a lot of that in this case n times n minus 1 times n minus 2 etc now we need a base case we just need to know where does this stop at so we don't have an infinite loop so what's the performance story on all this though what if I wanted to call a factorial 100,000 what am I going to get back actually get back nothing I'm gonna have a range error maximum call stack size exceeded so what is that actually all about does that mean that we can't do recursive functions that this isn't going to work not necessarily but what what does it actually mean so what what's going on here let's go back and trace through these calls and let's put a call stack next to this so we call factorial 4 imagine the call stack we add an stack frame for this particular call we know it makes a recursive call to factorial 3 so let's have a stack frame for that same thing with factorial 2 factorial 1 but notice what's happening here our stack keeps growing and growing and growing thankfully we've reached the base case here so we can start popping off the stack frames and getting back answers but what happens when we do factorial hundred-thousand so the stat grew order of ov in so a hundred thousand calls means a hundred thousand stack frames then depending on what environment year you're in when I did some of these calculations I was an older version of no but at that time a stack frame was usually around 48 bytes the max your call stack could grow would be around a megabyte little less than that so a hundred thousand times 48 converting etna megabytes we attempt to use 4.5 eight megabytes and we were limited to less than a megabyte so that's why we got this particular error so does that mean we can't solve this particular issue with recursion not necessarily so another thing in es6 is this thing called tail call optimization it's a really powerful concept in functional programming where we could treat the problem this recursive problem if there was some way instead of growing the stack we could just replace stack frames because we're basically solving a problem in terms of itself and so the critical key point to this is we need to make sure that the recursive call happens in what's called the tail call position which essentially means it needs to be the very last statement in our return statement the very thing that's very less thing that's evaluated in our return statement so our original example we couldn't you can optimize this for tail calls and you know I'm saying well there's factorial it's in the return call it should be fine right if we follow the order valuation here we have n minus 1 then we have factorial of n minus 1 but the last thing is we still need to perform this multiplication step so we are forcing the program for every recursive call it has to wait on the recursive call to come back before it can finally produce an answer therefore we have no choice but to keep growing the stack but we could change how we define the function and make it optimizable and what we're going to essentially do is actually just introduce another argument and this is usually the the typical pattern you use when you need to make tail call optimized functions is you want something that's called an accumulator and so we're going to call it a cume for short we're going to use the default value for the parameter and set it to 1 and so typically you want it to start off with whatever your base case return value was we knew that was 1 so when n is less than two instead of returning one will return whatever accumulator is but the critical thing here is now we've moved that multiplication to inside the recursive call so we still have into my swine but now we're doing in x q and so as the name suggests an accumulator it's going to start accumulating the final result through each recursive call so the order evaluation here now an minus one n times a q and then finally now the factorial is the final statement in this return statement and now we can optimize this so what that means is if I know that I can call a factorial with a certain number and it basically is no different than calling factorial with different arguments there on the bottom and I could theoretically just replace stack frames and we'll see that so if we do it we now to get back about you you get back infinity but that's just because of number overflow issues in JavaScript but that means we can solve these problems to a certain extent still with recursive functions so I mentioned what does this look like now with the call stack again we do in fact toilet four we have an implicit one there remember we're just using the default values let's buy commented it out so we've had this stack train with factorial a four and one it's going to make a recursive call to factorial 3 & 4 so actually we could say factorial of 4 & 1 is no different than calling factorial 3 & 4 therefore I can just replace the stack frame with factorial 3 & 4 well that's no different than calling factorial 2 and 12 so just replace that and that's no different than calling factorial 1 and 24 and notice there on the right we've been accumulating our answer remember 24 was the final answer here so we've just been accumulating it in that second argument position and then we've reached the base case so we'll just return that that's how we can solve these type of recursive problems still in an optimized way thanks to this new feature in es6 and I believe it's actually natively available now in the latest version of Safari although Babel is able to basically do this for you under the hood if you want to transpile it as well so wrapping up we covered a lot of topics here I just want to recap and kind of see what we've discussed and why it was important we talked about some principles predictability we have pure functions we have the quality of style programming that allowed us to have better guarantees better deterministic outlooks on how our functions are going to operate and that helps us have better trust in our programs that we're not necessarily always going to run into subtle issues and bugs especially the mutable state we also talked about this safety we want to use immutable state create new state we also want our state to be transparent outlet open we don't want to just hide it all behind objects that we send messages to and then we talked about this modular concept that we can take tiny tiny pieces through currying through composition and we can build up more and more complex patterns more and more complex functions just out of that and solve actually decent problems so I just want to leave you with some final resources these slides will be on available online as well this is Professor frisbees mostly adequate guide to functional programming I it's becoming definite required reading for someone that wants to do functional programming in JavaScript brian lonsdorf is very very intelligent smart K and I highly recommend checking this book out he covers a lot more than I do and probably more eloquently than I ever could so definitely check this book out we've been talking a lot of is six two and if you want to utilize that especially for older browsers I highly recommend checking out Babel so you can transpile code into equivalent es5 code that can run in older browsers if you want to try out a different language it actually trans files to JavaScript I highly recommend these languages element pure script our Haskell inspired languages and very very powerful language especially Elms becoming much and much more popular there's also clojurescript which is basically an implementation of closure for the browser if you've not heard of closure it's basically a lisp that runs on the JVM some libraries that we've already mentioned for lodash rammed great functional libraries it's also RX GS and bacon JSF you want to check out reactive functional programming and then of course we already mentioned a mutable Jas that allows you to have immutable data structures and then for the MV star crowd of course I'm going to highly recommend the act and redux which definitely espousal out a functional concept so if you want to potentially take this somewhere else I would highly recommend them at the very least utilizing Redux to potentially handle your application state even if you're using something like angular and with all of that thank you all so very much for joining me and there's links for codes and slides
Info
Channel: Jeremy Fairbank
Views: 29,993
Rating: undefined out of 5
Keywords: javascript, programming, functional programming, web development
Id: HvMemAgOw6I
Channel Id: undefined
Length: 57min 54sec (3474 seconds)
Published: Sat Aug 13 2016
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.