Learning Functional Programming with JavaScript – Anjana Vakil – JSUnconf

Learning Functional Programming with JavaScript – Anjana Vakil – JSUnconf

January 23, 2020 100 By Stanley Isaacs


[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]