Learning Functional Programming with JavaScript - Anjana Vakil - JSUnconf

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

She's great, I wish she had a youtube channel

👍︎︎ 3 👤︎︎ u/jaredcheeda 📅︎︎ Aug 07 2016 🗫︎ replies

I love her enthusiasm, but I can't help but feel a bit infuriated by this. Why does it seem like so many JS devs are trying to turn Javascript into something that it isn't by throwing as many libraries as possible at it?

Turning an array into a node tree, just so you can replace nodes instead of ...replacing members of an array? How is that actually different?

Don't use loops? Only use ...methods from the Array prototype? Convenient that it's preferred to utilize prototypal inheritance when it's beneficial, but not to write it yourself. Not to mention that no matter what iterator function you're using, native loops are literally always going to be faster.

I just really don't understand the incredible lengths people are going through to not do things the way they've been working for a long time now. I'm not saying OOP is perfect, but I don't see the point in doing anything you can to avoid it just because you're scared of using this.

👍︎︎ 5 👤︎︎ u/memeship 📅︎︎ Aug 07 2016 🗫︎ replies
Captions
[Applause] Hi! First of all, I just want to give a big shout-out to the organizers of this conference. I feel like this has been a fantastic smooth experience from start to finish, so... [Applause] Amazing job. Hi! I'm Anjana Vakil. I am an English teacher turned computational linguist turned software developer and as I mentioned a little bit earlier today, about six months ago, I knew nothing about functional programming and very little about JavaScript. So, what I want to do today is kind of take you guys along on some of the things I've learned about doing functional programming in JavaScript and I am not an expert in any of this, so this is going to be me taking you along on my learning journey and nothing more. I'm going to try and save a little time for questions at the end, but we'll see how that turns out. So, how did I end up standing here talking to you guys about functional programming in JavaScript? About six months ago in the fall of 2015, I went to a programming community in New York City called The Recurse Center which quick plug is probably the best programming community I've ever experienced and it's a programming retreat where you can go and learn about whatever is interesting to you in the world of computer science and so I got there and a lot of people were talking about functional programming, functional programming, Haskell, Clojure, all this cool stuff, a lot of people were working in JavaScript getting into node and these were some really interesting topics and so I started talking to people there and finding out what is all this stuff. So, what is functional programming? Few different ways that question can be answered. First of all, it's a programming paradigm. Some other paradigms are like imperative programming where you say do this and then do that or object-oriented programming which maybe a lot of you write object-oriented JavaScript where you have objects and they have methods on them and you change them, etc., etc. Functional programming is also a paradigm where functions are king and we'll talk about what that means in a little bit. It's also a style of coding, of organizing your code, writing your code, style of approaching projects and really more than that it's kind of a mindset you can get into, a way of thinking about a problem, a way of approaching a task and it's also a really sexy trend with lots of buzzwords that'll make you super popular when you're talking with people at the pre-conference party or whatever it is. No, just kidding. But it is something that's gotten a lot of attention and, so yeah, I thought it was important to find out why everybody was so excited about it. So, why do functional programming in JavaScript specifically? Well, I don't know about for all of you, perhaps more experienced JavaScript developers, but when I started learning JavaScript having had some object-oriented programming experience with Java, C-Sharp, that kind of thing, I found object-oriented JavaScript super confusing, prototypal inheritance, how does that work? How many of you guys, quick show of hands, have ever run into a bug or a problem or something unexpected with this, doing something... Yeah, exactly. Right? So, I found that really tricky and confusing and so I thought, all right, I know I want to get more into JavaScript but let me set aside the object orientation and try to think about things in a functional way which is maybe simpler in some ways and avoid some of these problems like bugs introduced by binding this to the wrong thing. So, functional JavaScript to me at least is a bit safer, a bit less tricky, a bit easier to debug but easier to maintain as you're building a project and we'll take a look at some of the features that make that easier in a bit. Also, there is already a huge community of developers who are doing JavaScript in a functional style, so there's a lot of libraries out there to help you write functional JavaScript. There's a lot of people out there that are experts in this, for example, there was a talk in the next room over earlier today on Ramda and there are people here you can talk to that probably know a lot more about functional JavaScript than I do, but the point is there's already a community, so this isn't necessarily something you'd be doing on your own, grappling you versus JavaScript, there's other people to support you, which I found really helpful. Okay. So, hopefully by now I've convinced you that functional programming is at least interesting and that we could do it in JavaScript to avoid these headaches, etc. How can we do it? What does it mean? This is what I was asking myself. So, the main thing and maybe it sounds like a tautology or obvious is that in functional programming you want to do everything with functions, so we want to express everything in our program in terms of functions. And a function of course is just something that takes an input and gives an output. So, we want to be thinking about kind of the flow of data of inputs and outputs through the program, instead of thinking about objects and how they interact and how they manipulate or thinking about steps in a recipe like in an imperative style. Here we're really thinking about how we can express everything in terms of functions, taking inputs, giving outputs. So, for example, this would be a non-functional way for me to get the text “Hi, I'm Anjana” to appear on the screen. I could assign a variable, I call it “name” and have it store the text “Anjana.” I could have a greeting like “Hi, I'm” or “Hello, I'm”, whatever, and then I could log that to the console. This is sort of an imperative style. First do this, then do that, then do this other thing, we don't have functions here, we're not expressing this in terms of how inputs are transformed into outputs. So, maybe a more functional way of doing the same thing and this is a really simple example, just for the sake of it, is to define a function called greet which takes a parameter name and returns a string which adds “Hi, I'm” to the beginning of that name. So, for example, if I type greet, the string Anjana, feeding that as input then I get the output “Hi, I'm Anjana”, that's a more functional way expressing this in terms of functions. Okay. So, another... maybe the main thing about functional programming is to avoid side effects and instead to use pure functions. So, what does that mean? A side effect is anything that a function might do that isn't computing its output from the inputs you've given and returning that output. So, for example, printing something to the console is not returning an output, it's doing something else, something that's on the side of the function or if you have a function that uses some globally defined variable to compute its output that doesn't depend only on the input to that function, so that's not pure. It's taking something from outside the function and involving it in some way in what the function does. So, this is just a really quick explanation of what a pure function that avoids side-effects would do. For more information on that there's excellent Wikipedia articles on these sorts of things, but basically the idea is that you want your function to do nothing except take its input, use that and only that to compute an output and then return it. That's pure. So, for example, this function here, we have this globally defined variable name which gets used in the function as you can see in the last line there, it gets used, so there's no input, we don't have name as an argument to this function, it's just reading something in from the global state. That's not pure. Also, not pure because the return value of this function here isn't what we care about, we care about doing something, changing the world in some way other than the return value, in this case, printing to the console. So, this is a not pure function here. A pure function might look like this. Here we have, the only thing that matters to the output of this function is its input, the argument that we pass to it and the only thing that it does is return its output. Okay, so I've been talking for a while now about pure functions that's because this is really like a key thing at least for me, something I've taken as one of the key parts of functional programming is thinking about things as purely as possible. Another key point would be using higher-order functions. So, this means functions that can take as inputs other functions or a function that can return a function as its output. So, basically, we're treating functions kind of as objects themselves. They can be passed to other functions. You can have layers of functions within functions within functions, etc., and these are what's called higher-order functions, they come up a lot in functional programming. This is a bit of a random example, but let's say we have this function at the top here, makeAdjectifier where we give it an adjective and it returns actually a function. It doesn't return a string or a number or anything like that, it returns us a function which adds that adjective to a string that you give it. So, for example, I can use the makeAdjectifier function feed it the input “cool” and get a function that's called coolifier. So, now when I pass a string to coolifier, I get “cool” added to that string. So, if I pass conference, I get cool conference. So, the idea here is that we have a higher-order function which returns a function. And this kind of wrapping your head around this at least for me is one of the key things to being able to write in a functional style because as we'll see a bit later, we need these higher-order functions in order to avoid some of the tricks that we're used to using from other paradigms. So, learning the thing to get into that functional mindset for me really involved wrapping my head around this concept. Okay. So, one of these things that we're going to avoid that we're used to doing is iterating, using like “for” or “while”, these sort of things. We're used to going over lists and doing things to all the items in it. Instead, in a functional style, we might use higher-order functions like Map or Reduce or Filter which often take as an input not only the list that you want to do something to in some way but also a function that then you're going to apply to it. In the interest of time I'm not going to go into too much detail about what Map, Reduce, and Filter do, but I found and also thanks to my colleague Khalid up there, a really cool graphic that I think expresses Map and Reduce pretty well, maybe you guys have seen it before, the MapReduce Sandwich, everyone! So, the idea here is that let's say you have a list, in this case, a bunch of vegetables. They're whole vegetables. We got some bread in there too and we want to transform that data in some way. So, for example, let's say we want to slice that data and we have a function ‘slice up’ or ‘cut up’ or ‘chop’ which we can apply to each item in that list. Now, usually I would do “for vegetable in sandwich ingredients,” do all of this, do all this chopping, but in a functional style we'd use Map, give it the list of ingredients and give it the function ‘chop’ and I would get out a new list where everything has been chopped. Then we have a Reduce function which basically combines all of the items in a list in a certain way, in this case, layering to make a delicious sandwich, and Filter let's say could be if you hate cucumbers, you could have a Filter function which makes sure that only things that are not cucumbers get through the filter. So, these are the ways we use these higher-order functions to get around the type of “for” or “while” iteration that we're used to doing in functional programming, instead we're going to feed functions to higher-order functions like Map, Reduce, and Filter to get the sandwich that we want. And again, this is not intended to be a totally clear explanation of how Map, Reduce, and Filter work, but there's plenty of information on that online. The idea is that we want to use these instead of “for.” So, another thing that we want to do is we want to avoid mutating data, |avoid mutability. Mutation in the sense I just mean changing objects in place. So, when we have something that's immutable, I'm sure a lot of you guys are familiar with the term, it's something data that can't be changed in place. Once we've set it it's there forever. It's never going to change. So, let's take a look at an example. Just because for me this was another thing that required a little head wrapping. So, this would be an example of mutation which is non-functional. We have a rooms variable which stores a list, so “H1,” “H2,” and “H3,” because that's what we thought the rooms were, at least that's what I thought the relevant rooms were, and then we say no no no actually it's not “H3,” it's “H4”. So, let's replace the thing at index [2] in rooms with “H4.” And so, then we have rooms has actually changed, we went from [“H1,” “H2,” “H3”] to [“H1,” “H2,” “H4”]. So, that is still stored in the variable rooms but we've actually changed something in place and this is something that functional programming avoids because this can cause a lot of problems and this is part of the reason why we get into trouble with this and with these sort of object-oriented approaches, sometimes you can change things in a way that you didn't intend, so that what you thought you were dealing with if I thought that rooms meant [“H1,” “H2,” “H3”] and I didn't know that somewhere else in my code I had replaced something in the rooms array I could run into trouble. I could end up introducing bugs into my code and having a really hard time tracking them down because rooms here is the right thing, rooms there is the wrong thing, ah! what happened? Where did this go wrong? Oh! my God! You end up crying in front of your computer. No, just me. So, a better way to go about things is to think of all data as immutable, never changing. For example, with no mutation we still have our rooms which has the wrong [“H1,” “H2,” “H3”] but instead of changing it in place I'm going to make a new rooms array using this map function that we talked about a little bit earlier where I'm mapping, I'm feeding a function into this map, which looks at each room in the list and if it's “H3”, oops! I have a missing = sign there, last-minute slides, if the room is “H3” it returns “H4” instead of “H3”, otherwise it returns whatever the room was. Okay. Understanding this specific example is not crucial but the point is that once I've assigned this new rooms variable, new rooms has the correct values I expect “H1,” “H2,” and “H4”. But rooms is the same as it always was, it hasn't changed at all. So, this is thinking about rooms as being immutable, we're not changing it and that's something that's really important for functional programming because as I said, it helps you avoid a lot of headaches, a lot of bugs. So, how much time do I have? Okay. Good. We have a little time to talk about persistent data structures, yey! The problem with immutability is that when you're treating arrays and things like that as immutable, what you end up doing is making new copies of everything. So, if I want to change my one room in this list I have to make a whole new array and when you're dealing with short little things like this maybe that's not a big deal, but as your objects get bigger, more complex, this can give you efficiency problems because if you have to copy over everything, even the things that didn't change, every time you make one little adjustment and you want to make a new copy, a slightly different copy of your array, it takes you a lot of time, you have to go through everything in the list to copy it over, you end up using a lot of space that maybe once the objects start getting bigger and bigger becomes a problem. And so, one thing that's very popular in the functional world as a way of getting around these efficiency issues is to use persistent data structures. This was something introduced sort of theoretically by Phil Bagwell, he wrote a paper called Ideal Hash Trees. I can put a link in the slide to that later and then Rich Hickey who invented the language Clojure implemented the data structures using Bagwell's ideas to make Clojure really efficient for these immutable data structures and for these functional operations. Okay. So, the way persistent data structures work if I may, if you will indulge me, I'm going to step back to the chalkboard right here. We're getting retro. Yeah, it's happening. Okay. So, if we have like an array where we had H1, H2, H3, typically what I do in a mutable world is just get rid of this and replace it with H4, but as we said we want to avoid that. So, instead, if I copy it over into a new array, I copy H1, I copy H2 and I replace, instead of copying H3 I put in H4. Great! But now I have to store two arrays, taking up a lot of time, look how long that took me to do all of that. Terrible. Right? I know you guys feel as upset about this as I do. I can see it in your faces. What if instead we represented this array right here as a tree, such that each leaf node of the tree is one of the things that I'm trying to store or perhaps 2 of the things or 3 or 32 or some number of the things and if I want to change something, I don't need to replace the entire array, I can just make a new node over here, like H4, and now I can make a new tree which instead of repeating H1 and H2 I can reuse those same things and just make a new node which connects them to my new element over here, so that now I have here a data structure which contains H1, H2 and H4 but I didn't need to make a whole new thing. I just needed to make my one little part. I can reuse the old structure of the list. So, this idea, this sort of topic is called structural sharing because we can share parts of the old versions with the new versions, so we have much more efficient operations for adding, changing things or moving things from vectors, for example, or arrays and this can also be done for maps, for hash maps that sort of thing and it basically makes the world of functional programming bust wide open so that we don't have to go through these long time and expensive space operations to update our immutable data all the time. So, to do this in JavaScript, there are a couple of libraries that are really popular. One which I like to use is called Mori which I'll show you the link for in a little bit which actually uses ClojureScript which has these type of data structures natively, it ports them over to JavaScript, so you can use them right from JavaScript and it's great. It has a lot of also like general functional programming helpers like Map and Reduce and lots of other things. There's also another popular library called Immutable.js which Facebook put out which is JavaScript through and through. I haven't worked as much with that but I know a lot of people like that as well. And yeah, so these are ways you can try out using these immutable data structures if that is something you feel like you can't wait to do now. I know. I can just feel the excitement. Yeah, that's great. Okay. Moving on. If you're ready to try it out, like I said, we have Mori and Immutable.js, links there to those libraries. There's also a lot of utility libraries which don't focus so much on this persistent data structure thing, but instead give you a lot of helper functions like Map, Reduce, etc. So, Underscore, Lodash, for example. Today I found out that Ramda is a thing because there was a talk on it the other day and there are many more. And in fact, JavaScript has some built-in functions, like for example, arrays have a built in Map, Reduce functions. So, a few slides ago we saw this rooms.map, that's because the array prototype has these functions Map, Reduce, etc. So, you can even do some functional programming in pure vanilla JavaScript without using any of these libraries. Okay. So, if you are sitting there thinking, What? Huh? I didn't really get that something about immutability, side effects, pure functions. What now, huh? If you want to learn a bit more about all these buzzwords, like I said, all these sexy buzzwords that I've been throwing at you for the last 20 minutes, I highly recommend a nice gentle introductory article called “An introduction to functional programming” by Mary Rose Cook who is a former facilitator at The Recurse Center that I keep talking about. The link is up there, but basically this is a really nice introduction that kind of goes into a little bit more depth in some of the “commandments” of functional programming that I've mentioned today. So, if you are a little intrigued but not quite clear on this stuff that I've been mentioning, I highly recommend you check it out. So, I think that's it for my talk. We have a couple of minutes for questions, I suppose, eight minutes by my account, but first of all I just wanted to say thank you guys very much. I'm Anjana Vakil. Anjana Vakil on Twitter and has link there to my GitHub. So, would love to keep in touch if anybody else is out there also learning functional JavaScript as a newbie like myself, definitely reach out, we could stick together, but first of all I want to give a huge thanks to again the JSUnconf organizers, especially the diversity sponsors. I'm here on a diversity ticket myself and wouldn't have been able to come without that awesome program and all of you and the sponsors who sponsored those tickets and also a huge huge thank you to The Recurse Center and some of the alumni there who have helped me learn all this stuff including Khalid at the back there and Sal Becker, another alum, who explained a lot of this stuff to me over several long caffeine-fueled conversations at The Recurse Center and if any of you are interested in spending time on self-directed educational programming retreat in New York City definitely check out recurse.com, it's an amazing community. Okay, that's it for me. Thanks. [Applause] Thank you very much. Yes, _____ Does anybody have any questions about functional programming? Don’t know if I'll be able to answer them but I can try. Yeah. Actually, always the professors at my faculty always said that object-oriented programming is better than functional programming and I was thinking that is it better or is it you think that we should use functional programming only on JavaScript or also on other programming languages like C _____ So, I think that's a great question and it kind of gets into a little bit of the, what I think of as kind of the philosophy of programming paradigms. So, as I was learning about functional programming I started even wondering what is a programming paradigm and why do people fight about them, why do people say object orientation sucks, we have to do everything functional and why do people say no, functional programming sucks, we need object orientation. And the conclusion that I came to is that no one paradigm is better or worse than other paradigms. They just have different advantages and disadvantages and they have different situations in which they're going to be kind of the best tool for that particular problem. So, for example, if you just want to really quickly write up a script that just does something on your computer once really fast, you're probably just going to do it in an imperative style, do this, then do that, then do the other thing. If you don't need to maintain it, if you just need it to happen right there, imperative programming is a totally legit paradigm for that. If you're trying to model real world objects and how they interact and how they go around and things you can do, like if you're trying to model, I don't know, books in a library or classes with teachers and students and how they all interrelate that sort of thing, maybe thinking about it in an object-oriented way makes most sense because that's exactly the problem you're trying to solve, is modeling objects and that's why that paradigm came about. But if you're trying to avoid some of those problems that I was talking about when you have maybe a situation that doesn't actually refer to real-world objects, where you're using objects just because you have to and that's introducing all kinds of side effects and weird bugs that are hard to track down, maybe you want to consider thinking about it in terms of functions on your data and things being pipelined through multiple functions and undergoing various transformations, not in the sense that the data is being mutated but in the sense that we're getting new outputs based on old inputs, then functional programming is probably the way to go and it has a lot of advantages such as being nicely, you can break things down into small functions that only do one thing. So, if you want to change something you don't have to change an entire class structure, you can just change the one little function that does the thing you want to change. So, I think it has advantages, it has disadvantages. I definitely wouldn't say it's better than object orientation in all cases and I definitely wouldn't say object orientation is better in all cases either, it really depends on your situation. Also, very good introduction of programming philosophy. I used to be a philosophy major, so that might be why. Any other questions? You mentioned Map function and the Map function is not working, so do you mix it... Before that, I come from object-oriented programming style and not so much into functional. That’s cool too. The professors really just test our functions and can avoid the concurrency that the Map function could possibly introduce. Non-blocking and concurrency and promises are all things that I do not feel qualified to talk about right here. I would love to turn that question over to the audience though. Anybody want to respond? _____ Fight fight fight. Just kidding. Just kidding, just kidding. That would be against the code of conduct, you guys. _____ I would also guess that perhaps it's blocking but we can discuss this later in a small room or outside. [Laughter] Thank you for the conversation starter question though. Excellent question and I would love to know the answer. Look forward to talking you guys more. I guess... I guess we are done with the talks, the big talks now. Thank you. Thank you. - Again. [Applause]
Info
Channel: JSConf
Views: 2,200,678
Rating: 4.8759065 out of 5
Keywords: javascript, functional, programming
Id: e-5obm1G_FY
Channel Id: undefined
Length: 29min 57sec (1797 seconds)
Published: Tue Jun 14 2016
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.