Practical Functional Programming in JavaScript - Ben Katz

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] okay so I'm Ben I work for Wix at front-end development for the premium team I want to talk about functional programming in JavaScript and actually practical functional programming I'm not just adding that word for nothing I think a lot of talks about functional programming today are super advanced and they talk about very high very complicated concepts I'm not going to go into the complicated parts I'm gonna stay pretty on the surface just because I think a lot of people are missing that part and I want you to get it so let's go on ok so what's so great about functional programming why do I want to talk about it why do I like it so for the next 45 minutes I am going to talk about why I like function why you should like functional programming why you shouldn't some of the basic concepts what are the benefits of this paradigm well if you're using these concepts what are you going to get from it and some more advanced stuff like the cool stuff okay okay so I'll start off with what it's not what's not better about functional programming and well it's just not better I mean I'm not here to tell you that you should always do functional programming that'll be a mistake it's just a different paradigm the object-oriented is one paradigm you have different paradigms others and I'm not going to tell you that you should use always one you should always consider your circumstances ok so like I said it's better suited for certain types of operations and it will fit it for others and let's uh okay the clicker is not working very great ok so let's see what what is it good for so stateless operations a lot of times server code like services are stateless and if they're not they should be and and in these cases a lot of time functional programming helps because there's no state obviously so you can just write functional code algorithms it's kind of the same concept when you do data data analysis sometimes when you have even on a client you have a service that takes data and returns some kind of aggregation on that data and those cases functional code is great also handling events and it's really good for testing you know - I'll show you I'll show you more examples later of everything here but generally is it I mean when you test something with input and output it's much easier to test you can you can understand why so when is it not great in my opinion like when you have a real state in the like wizards or that kind of the UI sometimes you just want to have state and in these cases a class could sometimes with the state could sometimes give you a better service and something you know functional code has to in today's JavaScript to my to my experience it has less advantage with speed if you use loops sometimes they're just better than recursions for example also with my experience it takes time to get used to writing functional code you have to practice it before you're really good at it and even to read functional code I have people who work with me and I am writing my my code which is somewhat functional anyway they used to have asked me to explain what what the heck this code does so it's not that simple now I want to talk about back to the future because I think it's really funny how back to the future awkwardly predicted the future wrong for example like this is how they thought the cool people would dress in 2015 and now you know that's just awkward even if you think of 30 years in the future or hoverboards like that's pretty weird and actually how they thought Michael J Fox would look when he when he'd be is 47 when he actually looks like this in 49 so those are those are awkward future predictions in opinion and the reason I'm showing you this is because I think I guess the future better when I gave this talk three years ago I actually kind of predicted the functional programming would be a trend I think like giving myself credits here so what I said back then is I had to I had to give like examples of languages that are somewhat functional for example Scala or link extensions and today I don't I don't need these examples I have Redux and I have immutable J's everyone knows what Redux today here and everyone knows that functional programming is like a really hot trend right now like if you google if you're Google on YouTube you get so many talks about it almost make this one redundant okay also you have languages these are all functional languages that transpile into JavaScript I recommend trying them just to get the hang of what is what is what it means to write real functional code because javascript is a hybrid in the end and there's always trade-offs and it's so much trend it's really cool okay so I'll start off with the concept okay like these are the core concepts of functional programming if you have to understand these these are like building blocks that you need to know so what is the mutability the immutability means that when you have an object you never modify it you create new objects that have the modifications on them there's a lot of advantages to that react uses it a lot on Redux - I'm not going to go into how it how they how they are used but I'll give you an example what immutability means so if you have code like this you have this array it goes through map that adds more of one to each one of its values and then it goes if it's filtered now this array is a new array then from this I mean you don't actually change the values in this one once you go here this ones unless you I mean once yeah actually once once you go here this array is actually thrown because there's no reference to it and there's no need to keep it in memory so this is when I said like sometimes speed is not the most beneficial sometimes this causes actually slowdowns but you'll be surprised how in large frameworks this usually causes big speed ups especially when you need to compare you can compare by reference instead of by value and that's that's the biggest benefit oh man I have a problem with this ok another really important concept is first-class functions so these are functions that can be passed around that that's basically what it means you can pass a function into a function higher-order functions that's how you call them they're useful to avoid state and they're useful to obstruct solution and let me give you an example this function is a function it given a max value this is by the way does any does anybody here know what an arrow function is what is what it means okay you don't know whatever phone okay that's what I want to know because yeah okay that's what I want okay so raise your hands if you know what arrow function our okay cool so I'll just pick something because not everybody raised their hands it basically means that this is the parameters of the function and the result of the this arrow means that this is the result so if you give it max and number you get the maximum of Max and number okay so if this is like the previous max if Max was one and number was three then this will this is a function that will give you three now if I pass this function oh I'm going to use this okay so if you pass this function to max into the reduce of this array you will get four which is the maximum now if you switch this function by something else in this case this is a function I mean this is the mathematical notation but it means if you want to calculate a new average and you have the old average you have this formula I don't need to go into details I just want to tell you this is the equivalent the JavaScript equivalent you take an average you add something and it creates a new average and then if you take the same the exact same line but instead of two max you put to average okay you get the average of this array and this is basically a basic concept in functional programming we separated the values and the function the logic and that allowed us pretty nice operability with between these two concepts I'll show you a lot of these don't worry okay so I'm going to talk about ink ink is a very complicated function it takes values and adds one so if you take four you get a 5 for 0 you get a 1 for 199 you get 200 and for 2035 you guys are good I shouldn't notice is advanced okay so we'll look at three ways to implement this using higher order functions there are different ways to do it so number one okay we'll use an arrow function this is actually and I'll show you what it what it what I mean a function that returns a function look this I needed so I'm adding these round brackets because this is a function that takes B and returns a which is from the outside plus B and this is a function that takes a and returns a function that takes B that returns the addition so this is a higher-order function a function returns a function ok and when I run this function the big one on one what I get this is this function that the a is one so you get if you give it B you get 1 plus B and that's where you get Inc if I give it if I've given it something like minus 1 I'd get dick like decrement and this is a reuse reuse of function as a higher-order function let's see another similar example so this is another way to do it this is of the old-school way you take a regular function and you just bind it to a value this is the JavaScript yes five it's it existed law a long time ago undefined it's just this it doesn't matter here for this example so this basically means take this function and bind the first value to one so again this it returns one plus B which is surprisingly Inc okay there's another concept it's called caring caring means you take a function okay you take this function and you create a new function but everything here we'll be talking about functions taking function returning your function so I'm sorry this is a little confusing please just raise your hand I'll explain it five times if I have to but basically what this carry what it does it takes a function and it returns a function that when you pass what a parameter like for example if you pass one parameter it returns a function expecting the second parameter it's cut it's kind of like the partial application that we've seen but it's very dynamic you know without going into too much explanation you can play around with it later again you do the same as we've seen before you give it one and then you return a function that given six returns seven or two times three and this is very very helpful for functional programming why I mean what will seem in the rest of the talk okay so when we work with functions we can't just use any function because we have certain expectations one of the expectations is that our function would be stateless what does it mean to be stateless it means that it doesn't use any values that exist outside the function for example global variables it can't access it can't do an object called it can access the window or a dome in any way it takes the only thing it takes is the parameter of the function and it returns the value based on these parameters that what that's what stateless means no side effects it's kind of the same but but outward it can't create side-effects if it doesn't object requests for example that's a side effect it will influence some something in the outside world you can't do that and if you take these two and combine them you get it for every X f of X will always be the same it does it this sounds mathematical not by chance functional derives a lot of its of its abilities from being very mathematical and if all of these applied it's a we're calling these pure functions ok pure functions are functions that a bye to all these broke rules so this is purely I'll give you an example in JavaScript we have splice and slice I'll give you a little bit background splice is the function that given this array weight given this array and the number one changes the array the the one we read it ran of and really remove is the first if this is one it starts the array from to you like it removes the first element so what it actually returns the element removed which in this case would be one one is the index yeah it's not value and the this value will be changed slice works differently it's very similar but it's stateless so if you run slice on this function you get as a result the array two three but this for this array doesn't change it doesn't touch the existing array so when we do functional code will want to use slice not splice okay so I kind of answer the question slices the pure one okay so why why do we even need all of this why I mean it's there's some concepts here but what does it help us how does it help us one thing it allows us to do is optimize a automatic compiler optimizations so for example look at these three functions you have you have X that's dependent on the function f and you have Y that's dependent on the function G and the value from the previous line previous line so to calculate Y you have to run both G and F but if you look at Z okay actually you don't use the values there anywhere you only use y2 console.log here and that's important because in practice what it means here that you don't actually need this line you can just remove it and never call for F okay because the value of Z is never used what is it now why can we do it if F was had had some kind of a side effect we couldn't have done this because we couldn't know that we're moving this line could somehow not or impact or not impact our application but now we know because we know that F is a pure function we know we can remove it because it removing it doesn't change anything in the outside of the function so this is really important you can just remove this a compiler can do this automatically automatically if you know if it know that these are pure functions by the way guys you know stop me at any time it's okay okay another concept I mean I mean it's not a concept it's actually a nice thing to have in functional programming is memorization it's a funny word but it means basically cache okay so if you have this function which is pure and you run memoize on it you rat you actually wrap it with a function you get a new function that has cache automatically built in it just looks at it just looks on the parameters and recalls the the output of the function so you don't have to call it again with the same parameters so for example if I run it with two and three and I get five we can see that ad is called because this is the first time you call it and then you call it with different parameters one is three and you get 4 because one and three is different than two and three but if you call it the third time ad is not called and that's a really big benefit think about large systems with a lot of a lot of algorithms and a lot of calculation this could save many many cycles and it's used a lot like Aria you know if you use if you know Momo bik's it does just to save a lot of calls yeah yeah go ahead how does memoize work okay the question was how doesn't it was work so what it does it just I mean well there are different implementations but the basic idea is that it recalls how many parameters it have it creates a key based on these parameters for for you know hash table and what it like em add pass is 2 & 3 it sees that there's 2 or 3 it recalls 2 & 3 passes it to add internally gets the result from ad stores it in a hash table so it stores 2 & 3 the value is 5 okay and then returns 5 and next time you call 2 & 3 it'll it will check in the hash table to see if it's there okay no memoize is a it's not this this function is not built into JavaScript sorry this is a library function it's not a keyword memoize is I'm sorry maybe I should have said it nah it's it's a third party I mean there are many implementations for it's a concept member there is a concept of how what to do to a function but the implementation is not part of JavaScript it's third party libraries provided but it's not part of JavaScript okay how do you clear the cache it each library provides its own API so parallelization so let's say you take these two function they're not related this is part of being stately so that's what it means they have no they have nothing to do with each other so there is no reason why not to run them together in single in different threads and get the results sooner and then add the value but you can't really do it in JavaScript because you can't run two things together in JavaScript well you know as a concept like for it's important to understand this because if you ran on a server you can actually do this okay I wanted to I want to explain for a second why functional code is really good for testing because I think it's really good for testing it's really worth to know this so if you've read tests and I'm sure hope hope I mean most of you did you'd know that most testing library libraries like jasmine or mocha test runners actually looked like this you get the forage which is sort of like it's the thing that runs before all the tests it's it's called the setup and then you have the test and this have you have some more setup and probably some kind of an action expectation and then you have the after h which clears now usually the setup means side-effect like you know I'm mocking the server code etc etc or bi like mocking externality is now if if you have different setups per test you sometimes do this you have like different describes because different tests require different setups and this happens a lot so what functional gives you is cut all the down and just work with the actual function you just want to call the function with a value okay no call a function with the value and check the output that's all there's no setup for functional code and this works with components if you have a functional component meaning there's no state for the component and there's no dependency on add API I can assure you this is very doable I've done it and are in my project and this is how a test usually looks in these cases and it's really nice because it's really easy to detect problems when there is no side effect okay cash is a that's a good question cash is kind of a side effect but in this case it's very controlled I think there's no I mean if you know if you know exactly what it does and it's very controlled I think you can take I mean EP but it is a side effect just know there's no question it's definitely a side effect you know sometimes you can you can have some kind of trade off to get certain speed but yeah you're right I didn't you need hmm you notice I didn't show it as a concept just as in it's a benefit and that's why because it's really just a benefit okay something important that you need to understand when functional is and this is really I mean it's it's not directly related to functional but if you write functional code you'll probably also be writing declarative code and what does declarative mean so oh this picture is really packed pixelated so I'm just now seeing it I'll remember it for next time because on this screen it doesn't look like that okay so like what's a I'll start with imperative code imperative code is what most of you you probably have done you're right you take some kind of a state and you mutated you change it through instructions for example a loop is an imperative way to change a state and then when you like a function when it finishes with the loops and whatever you did with that global state you just return the value so that's imperative and that's kind of like a recipe for like preparing a cake you take the materials you do you do it like you get instructions what you needs to be done with these materials and when you finish you got a cake and that's your output now what's declarative declarative I'd say it's kind of like a menu like if you go to a restaurant and you have a declaration of the kind of food that the restaurant has you don't it doesn't tell you how to prepare it just tells you what the like what the cake has like if it has strawberries or vanilla or whatever so that's the clarity of code and that's like really abstract explanations so let me show you a real example this function reverses an array okay if you can see here you take you take the values of the opposing sides of the array like a mirror and you switch them until you reach the center and that reverses the array now this is imperative why because it explains through loop it tells you go from for each one for each cell one by one and switch it with the one on the other side of the array so that's instructions on how to reverse arrey I painted this on a piece of paper today I feel very proud of myself this is a declarative way to reverse an array and first of all you'll notice it's actually a recursion because here we calling reverse again on a smaller array now let me explain to you what's going on here to make it clear this is the input of the reverse it's actually the structuring it's a es6 feature for javascript it means that you take the whole array okay and you're separated by this structuring this is the first value of that array and this is the rest of it and we put the rest of it into a variable called ARR alright and then what we return is the rest of the array we reverse it recursively until we reach the end of it and we put the first element at the end okay so this is a recursive way to explain how to reverse an array and this works if you run this function on array it will reverse it so recursions are declarative which is pretty cool it's almost for free another another imperative example is how to manipulate Dom if you've worked with jQuery and who hasn't it's not a question everyone did knows that oops what did I do okay and so you know you take an element in jQuery or in the in vanilla dome and you just manipulate it in this case you take a container and then you create a button and you put the button on the container and you put the on click on the button and you tell it to add class to the class list so this is imperative way to create a button now a declarative way to create a button would be this this is the definition of the button and this is the definition of its properties and when you click it that's what it'll do unclick and the classes are just the state the value a decent state so it's not really stateless button but it's a we're not talking about stateless which you talking about declarative code so that's cool so declarative code is basically what pattern matching tries to be JavaScript doesn't have pattern matching but there is a suggestion to add pattern matching to JavaScript and this is what it will look like you will have so for example if you have a value whose an array and there are two values in that array so this will return the the addition of the two values same for object if there are two values with keys x and y it'll return some kind of whatever and if it's you know if it's there's just if the value is just the string hello which will return seven so this is very early-stage proposal don't expect it anytime soon so like like I showed you before functional programming likes recursions and the reason is that loops which are the opposite of recursions I'm exactly opposite but it's the other concept they have a state and we don't like state and loop so imperative like I showed you in the example recursion of declarative like I showed you in the example recursion they're basically a function that takes the previous state and returns the next state if you've done redux you know it's the exact idea of reducers okay let's look at an example of function composite what is function composition and this is a really important concept in functional programming this is a value and this is the list of function that you run on this value to achieve the value you want in this case you take the array and you map each one of its values to two times that value so you get this array and then you filter it through all the numbers that are divided by three and then you add all these numbers to get 36 so this is I mean this is starting to be more functional because we're using functions to describe what to do with this the only problem here is that it's really hard to separate the functions from the value we can't remove this value and use it and use another value with these functions unless you have wrap it with a function but that's that's a different example so the the right way to do this like the functional pure way to do this is to create a function by composing pipe is another way another word for a compose and that doesn't matter the details you take the three functions you connect them together through composition and the and this returns a function and the function that returns you run it on object and I'll show you an example now what it means so let's say we have these three functions that I show you one is called doubled one is called three divisible and one is add these are the exact same output we're going to get only we're going to separate the logic from the value and this is the idea with function composition then you take these three values and you compose them using pipe just if you're curious pipe is the reverse order of composed it's just a little easier to read for people who are not used to it okay and then you run the new function that's called manipulate on this is just an array from 1 to 10 and you get 36 again ok so we have the like the basic functions then we have the composition that we created it still has at this point there is nothing there is no value related we can do it we can do whatever we want with it and then we just run it on a value and we get the actual number that we wanted so it's better than changing because it separates concerns now let's take this idea and instead of running it on a on a big array like this this example if we had a thousand values in the array it would take a long time to run ok but whatever what would we do if we wanted to just take two items from an array of thousands how could we do this so lazy evaluation is the way to do this and I'll show you how it how it works right after I doing this so you take a big array like this let's imagine this is a thousand items and you run map on it okay this is not a lazy I'm showing you like how the non lazy version works and then you take these new items and you filter them because you only not like all the numbers that are divisible by three like the example and then you get like a subset so if this one had a thousand this would have like 300 whatever but you only wanted two of these you only wanted to the first and the second so you just take two now let's do a really quick little analysis on this and see how much space and time this takes so let's say we had a thousand and then map ran and we'd still had a thought it took a thousand units of time and created a new array with thousand units and then running filter on these took a thousand and this is I'm writing thousand it's less but it's the order of thousand okay when we finish this we have two thousand they took a two around two thousand units of time a 3,000 units of space that's a lot like if you think of big numbers this is a lot of time and space if you use lazy evaluation here first of all we know that we're going only to take two and that changes how we look at these so lazy means we take one by one until we've reached those two so let's see we take the first one we map it we filter it it passes the filter and we take it so we have one then we start with the second one we map it we go to filter filter stops it and then we go to the third one same thing until we reach the end and we have two items so we stop and it took a lot less time because we actually only analyze three items out of the thousand outside so if we do a quick analysis here we see that the space we still have a thousand because we started out with an array of the size 1000 we could skip that part but time took us only six plus some kind of constant because we don't know how much filter would filter out and like I said there's still a thousand in there and we want to take that thousand out we want to make it a constant how do we do this so if we had a generator function instead of an array so let's put a function a generator function here we could generate the values without actually holding the array for example if we're looking at a database we could generate functions from the database as we go and save a lot of space and in this case let's just skip to the end we eliminated a thousand here so this is very beneficial this is lazy evaluation and I'll show you like a very small code snippet that shows how to do this this is a library called lazy you wrap the jet the function in this case just a function that gives you one two three four five six and in this case you take five the first five numbers so you'll get one two five and then you can map and get the power of two you filter these you still get the five numbers because we told it take five I mean until it reaches the fifth number it won't stop so this could have run more times than five but it'll stop as soon as it has it's five values and then when you do whatever you want with it in this case we sorted so this is a pretty nice example of lazy but there's one problem here it's not really a real world problem because we had a function a synchronous function that generated in numbers we never have synchronous functions generates values for us in real code because we always get the values from a file or from a server or from any type of some synchronous data by a data source and even events are sort of like user interface events or the type of data source and we can look at it as as an array of Awesome colonias values and I'll show you what it means so like I said you it doesn't really think way way so let's rethink event sort of being events that we pool we'll think of events as events that are pushed to us like user interaction we don't know when the next one will arrive and this is an example this is an Austin generator yeah I will give you like more details on this it's pretty cool it's like very very very very new for JavaScript this kind of API and what it does it just creates I said I gave it 999 but you can say infinite number the set of numbers and each number is returned as a promise this is this emulates uh you know like a file read when you get like 500 or whatever infinite duck text from a document and it's read takes 500 milliseconds so this actually when you do yield here you get a promise and the promise takes 500 milliseconds to run and returns a value in a promise so let's see how we use this so this is exactly like you did with lazy but this time it's asynchronous so what do you it looks the same if you look at it you do a wrap you wrap the generator and then you run map on it and then you map it again and then you take the first three values and you print it and in this case you will get the array of two four six because you multiple you added 1 and multiply by 2 but what you don't see here is that this actually ran by waiting for genomes to return a value every time so if genom for example was generate user events you could have treated it that you could have done some really cool stuff I'll give you an example of that with a nice drawings in a second but what I want to say this is another example that does something similar but with for each with the latest don't try to read the code with the latest JavaScript this is the whole library that allows us this is very similar to rxjs if anyone here work with rxjs this is like a very naive basic implementation of our rxjs and with a current like a javascript it's really easy to write with uh you know with arcing generators so what it's really important for me to emphasize that there's a big difference between synchronous code and a synchronous code I events I mean that synchronous code is called the to decide where they pulled an x value a synchronous events are events that you don't choose when they'll they arrive whenever they are ready and you have to handle them somehow in a generic way and if you if this rings a bell it's actually it's the concept of reactive programming functional reactive programming where the idea here is that everything is a stream it's a stream of events so the idea here is that we relate to event as a temporal event a stream of events meaning the events arrive over time indefinitely you don't know if they're ever going to end you just treat them as they come and and you can't that's why you can't wait for all the events to arrive and just do something once they do so do you have to treat them as this as a stream so let's see I'll I'll give you an example this is a like the last thing I'll show you this is this is like really advanced stuff like if you have libraries rxjs works with react and you can and can make side treating side effect like the UI events very generic and very nice way to handle it so like I said think of streams as an infinite array of ongoing events and let's see the example so you start these are cliques okay we're going to I'll go to show you how to detect double clicks and on a user interface okay and this is a stream of clicks and you can see they don't come every 500 milliseconds or you just click whatever user wants to click this represent a click and how you handle it is you're on buffer which would throttle which means that ever if the if the sync if the clicks were clicked within 250 millisecond grouped them together do a buffer okay so this is what the array like the this is what it will look like as you go it will create these buffers but but it won't actually create those because we're already mapping each one of these into the length of the list so in this case you'll have one which is the size of the first one to the size of the second one three is the size of the third one and one of the last one so at this point you'll have a stream of events that are mapped into a one two three they represent a number of cliques together so what we're interested here at this point is just those that are big like higher than one like DoubleClick's or more let's call it like let's go three double click to so we're filtering everything that's bigger than two and we're left with these just two and three and these are double clicks and now you can take these this stream and you can use it for each to handle whatever you want and do whatever you want in the UI with it and this is a declarative way to handle double clicks if you ever try to do doubt handle double clicks without stream manipulation you'd find it very difficult it's really hard I tried it it's really really hard last thing I want to talk about is monads now just kidding I said I won't speak of monads so I'm not gonna speak that's it so yeah if anyone has any questions you're in shock okay from a what field yes definitely I mean you can okay the question is can you pass a function that takes values from the dome and then that way like you're asking if that's considered a side effect right basically it's still a pure function as long as you don't do any other Dom manipulation inside as long as everything it does it takes a component or a value of whatever from the dome does whatever it needs to do with that value and returns the output there's no side effect there's no domina pure no arjax yeah that's a pure function if your functions are what takes the value there's nothing other than return of value based on that parameter okay thank you [Applause]
Info
Channel: Wix Engineering Tech Talks
Views: 17,690
Rating: undefined out of 5
Keywords: Wix Tech Talks, Tech Talks, Wix Engineering, Ben Katz, Practical Functional Programming, Functional Programming, JavaScript
Id: zeZOPB9uxdE
Channel Id: undefined
Length: 42min 29sec (2549 seconds)
Published: Sun Mar 25 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.