Check out a free preview of the full Functional JavaScript First Steps course
The "Side Effects" Lesson is part of the full, Functional JavaScript First Steps course featured in this preview video. Here's what you'd learn in this lesson:
Anjana demonstrates how to remove side effects from an impure function. Side effects are produced any time a function depends on or manipulates data outside of itself. Pure functions do nothing but return output based on an input.
Transcript from the "Side Effects" Lesson
[00:00:00]
>> So yeah, so we are, now wondering, how do we go about, functional programming? Well, again, the core idea is that, we use pure functions. But what does this mean? What, mantra should I have, as a functional programmer, to repeat to myself, to remind myself how to do functional programming.
[00:00:23]
Well, that's what we're going to be talking about the rest of the day. And there are a few kind of guiding principles that we're going to get into in the different sections and the different exercises that we work through. But here are a couple of the main things.
[00:00:40]
Number one, we have to do everything with functions. Our program becomes, a function. So instead of thinking again about a program as like an imperative, series of commands, of we have to do this and then do that and then do the other thing. We can start thinking about our programs as, a function.
[00:01:00]
What are the inputs to my function, what are the outputs. So this requires us to think about our programs a little bit more differently. Instead of thinking, how should my program run, which is a pretty imperative question to be asking ourselves, we should be asking ourselves. What should my program take in.
[00:01:21]
And what should my program, return out. Again, this is all a consequence of doing everything with pure functions. So, let's take again a look at a couple of versions of, a program, on the imperative side, we have a series of commands. Store this string in this variable. Log this to the console.
[00:01:50]
Update this variable with this other string. Log that thing to the console. Imperative commands. Where For the inputs. What are the outputs? We're not really asking ourselves questions in the imperative Style. In the functional style our program here is this single function this greet function that we're looking at.
[00:02:14]
And the program takes into key inputs the greeting that you want to use. And the name of the person that you're greeting. And the output is going to be this. Hi, Alonzo, or Howdy Alan? Response this string? So we're now thinking about we have a program a really tiny, small little program, but a program for greeting people.
[00:02:38]
We are thinking about what are its inputs, a greeting and a name. What is its output a string and so this is what we're going to end up doing in the functional programming style is thinking about our programs as functions that take inputs and return outputs. So this means functional programs are a really great fit for things like again data transformation where you know what type of thing is coming in, and you know what thing you want to come out.
[00:03:03]
That is a really great use case for thinking about your code in terms of pure functions. And the other thing that we know that we're going to need to do functional programming is to avoid side effects. So we have to keep repeating to ourselves. Only return output do nothing else.
[00:03:26]
Only look at input, look at nothing else. So here's some code that has side effects. Real quick, who can shout out a side effect that this code is doing?
>> Assigning a new value to the thesis dot name property
>> Assigning a new value to the thesis dot name property, exactly.
[00:03:50]
So we have this thesis object and this function is updating it. It's affecting that object. Anything else?
>> Using the outside water data test, not then [INAUDIBLE].
>> Right? So reading data from the outside world, like this thesis object, that's information that I need to do my work here and I'm taking it from the outside world instead of the inputs to the function.
[00:04:15]
So reading data from the outside world. Exactly. Anything else?
>> You're logging to,
>> Logging? Yes, logging to the console, we've already covered that one. So these are the kinds of things that we're going to when we want to do functional programming. We're gonna have to watch out for those and try to find ways to conceive of our programs in a way that we can do the same work.
[00:04:37]
Without having those side effects, so how can we do that? Here is a refactored version, of this program, I'll let everybody take a look at, so now instead of updating, the global thesis object, what are we doing instead?
>> Creating a new [INAUDIBLE].
>> We are creating a new object.
[00:05:00]
So this is going to be a technique that we're going to get used to doing and we're going to talk about a lot later when we get into immutable data. Especially when we work with functional programs. We don't want to update things in place we want to take the old thing and make a new slightly different copy of it that we can return out.
[00:05:22]
So when we say things like data transformation, perhaps that's a misnomer because we're not really changing the data. We're taking some data and returning new data based on the original data. So in this case, we end up instead of a change thesis object with different values now we end up with a new object, and the old one is still the same.
[00:05:47]
>> So this is not a unary function that takes two arguments. You mentioned earlier that a pure function should only take one generally.
>> Interesting, okay, interesting point, does a pure function need to take only one argument? No, functions can take lots of arguments, and in fact in functional programming you end up with functions that can get quite large function signature, so lots of arguments.
[00:06:14]
And the point that I was making earlier about a pure function should only look at its input. By input, I mean, all of the arguments passed into the function. So let me restate that the pure function should only look at its arguments at the values that are coming in.
[00:06:35]
As arguments to it, and that might be one, or it might be a bunch, so we can, a term that often comes up in this is arity of a function. So the number of arguments that a function takes can be described as it already is. Again, we're not going to focus on these terms, but a single argument function could be called a unary function.
[00:06:58]
Two argument function binary et cetera. We are going to talk about why in functional programming you often end up with a lot of single argument functions, because it makes your life easier later on often. But no, there is no requirement and, excuse me if I misled or misspoke, that pure functions need to take only one argument, not the case.
[00:07:24]
Pure functions can take lots of arguments. And in fact, since they can't look at anything in the outside world, you often have to pass in a lot of data into the pure function because everything that it needs to do its computation has to come in through its arguments.
[00:07:40]
>> If this name the old thesis, it was one of the first inputs, if you assigned in a default value of thesis that would then turn this to be in pure function, correct?
>> That's a great question. So, let me restate if we assign a default value to old thesis that made it such that the default value of old thesis is this thesis object so that if I don't pass in an old thesis argument by default, I'm returning something based on the thesis, that we've already defined.
[00:08:23]
Does that make this no longer a pure function? Great question. So, in the sense that the function would then be looking at something that I haven't explicitly passed into it, we might get a sense that that's introducing impurity. However, we said that a pure function, it changes nothing about the world, other than returning its value.
[00:08:58]
If we pass in the default thesis value for the old thesis, does this function change anything about the world? In what it does, so I see some people shaking no, it's still going to return that new object. So it's not going to touch the thesis object, even if we pass it in as a default.
[00:09:19]
So, okay, there's one indication. And we said the other thing that we know about pure functions is that they're deterministic. If I call it with the same arguments I'm always gonna get the same result. So, if I have a default value for all thesis. And then I call it, let's say forget this thesis argument and I call it rename Thesis Church-Turing.
[00:09:43]
Am I always to going to get the same result? On the face of it, we might think, yes, as long as thesis stays the same, yes, I'm never going to get a different result. Now the gotcha there is that in JavaScript unlike in some functional languages we have objects like this are mutable meaning I could change something about thesis elsewhere in my program or my sneaky co-worker could come in and change it under my nose.
[00:10:15]
And in that case, I might get a different output if the value of thesis has changed between calls. However, later today we're going to look at how we can work with immutable data in JavaScript So that, I can be guaranteed because const thesis, the thesis object itself is never going to change and the values of the object.
[00:10:36]
If I work with immutable data in JavaScript, we can be guaranteed that the values of the properties won't change either. And so if with that asterisk, if I know that I'm working with immutable data, then I can be assured that I'm always going to get that same output.
[00:10:53]
And so I would still have a pretty pure function here. Does that help answer that question?
>> Yes. Thank you.
>> Awesome. And we're going to talk a lot about immutable data later. I love talking about immutable data. Super fun. So I believe the question is, can we use JavaScript's spread syntax to spread out the old thesis object.
[00:11:16]
And manipulate the data or return a new copy of the data based on those spread out values, instead of doing it this way. There's definitely lots of different ways we could write this code. This is just one way that we could conceive of doing this operation. Again, the trick with functional programming is to make sure that you're not changing anything about the outside world and that whatever that you're returning back is a new thing, a new object instead of that old object that you wanted to update.
[00:11:50]
And again, we're going to talk a lot about how we can do those non mutating updates later in the course. But essentially using things like spread syntax is really useful in in functional JavaScript sometimes especially when working with arrays and what not, we're going to, we're going to see that later.
[00:12:09]
And so that doesn't necessarily introduce any impurity here, unless you were, let's say, working with mutable or changeable objects as some of those values and then changing those objects. So It doesn't really affect the purity, what syntax we're using.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops