Check out a free preview of the full The Hard Parts of Functional JavaScript course:
The "Function Decoration Introduction" Lesson is part of the full, The Hard Parts of Functional JavaScript course featured in this preview video. Here's what you'd learn in this lesson:

Will demonstrates that although a function cannot be edited without it compromising its purity, function decoration as the appearance of a function being edited in its scope, but is instead creating a new function, and inserting in it the function that needs to be edited.

Get Unlimited Access Now

Transcript from the "Function Decoration Introduction" Lesson

>> Will Sentance: Function decoration. Now we convert our functions more easily to make them suit our task. If we're saving little blocks of code, little functions to be used again and again, little single tiny functions to be used again and again, ideally, I don't want to have to rewrite that code if they're slightly different.

[00:00:20] Now, there's one thing I can do, write higher order functions. I can have my function. Don't need to rewrite it, I just edit it. When I run it, I insert some specifics. The problem is I've had to have left a placeholder. Remember, higher order functions like copy, write, manipulate or map, I'd leave a little placeholder.

[00:00:35] When I run map, I specify exactly how I want to hit each element of the array. But sometimes I want to edit functions where I haven't left placeholders. I wanna retroactively give them new functionality. Problem with that people is, can I edit a function's body after I've saved it?

[00:00:54] Everyone together?
>> No
>> Will Sentance: No, I can't, exactly. Once a function's been saved, I can't go in. Arrays, individual elements in an array, I can add or remove stuff. Function code, once it's saved, I can't go back in there and interact with it, it's set. So we want to be able to edit functions but not rewrite them from scratch.

[00:01:19] So instead, we're gonna use a technique known as function decoration. It's going to appear to edit functionality that's being saved, it's going to appear to do so. It's actually not going to, though. Instead, it's going to create new functions or a new function, inside which the function we want to edit is going to be inserted in some way.

[00:01:49] Such that when we run the new function, it's going to appear to be running our function and with a slightly different behavior. It's going to appear to have edited our function. But actually, we've created a new function where we're running the function inside of it that we want to edit.

[00:02:02] And so that new function will look like it's the original function but edited. Here it is. So particularly if you want to add a permanent memory, for example, to an existing function we saved. Am I able to add the feature of a permanent memory, a backpack, to an existing function I've saved.

[00:02:18] If I've saved a function, am I able to give it a backpack after I've saved it? Absolutely not. The only way is for me to get it is if I saved it inside the running of another function and returned it out. So if I didn't do that, how can I give it a permanent memory?

[00:02:35] Well, there is a way. It's called, [INAUDIBLE] use it here. So for example, if I want to edit my function, here's a classic one. Suppose I want to edit my function, let's say multiply by 2, to limit it to run only once. So I can only run it once and from now on it's fixed to only run once.

[00:02:57] I run it one time, runs, no, problem, multiply by two, let's say we give it a ten. Run it again, it says, sorry, you've already run me. You can't run me again. This is a technique you wanna use all the time in programming. Often we wanna limit a function from being called, even in a game, for example, tic-tac-toe.

[00:03:12] You wanna limit a function to be called only one time on a given cell. You don't wanna be able to turn it from being a 0 to an X and then back to an X. You wanna limit it to run one time. Well, I can't edit my multiply by two function and give it a backpack to say you can only run it once, once it's saved.

[00:03:30] So instead I'm gonna do a technique called function decoration. I'm going to use oncify a function that's going to appear to convert my multiply by two function saved there into a version of multiply by two that is limited to run only once. But it's gonna be a big fraud.

[00:03:56] In reality, inside of oncify, I'm going to create a brand new function. Seth, will my brand new function inside of onceify have a backpack?
>> Seth: Yes.
>> Will Sentance: Yes, it will. I'm going to return that out. It's going to be called inner and stored in oncify multiply by two.

[00:04:14] And oncify multiple by two is going to behave just like multiple by two at least the the first time. But in reality, it ain't behaving like multiply by two. In reality, inside of it, it's going to run from its backpack the multiply by two function under the condition that upon checking the backpack, a counter is still zero.

[00:04:39] And then it's gonna increment a counter to say now it's one. And if we run oncify multiple by two, formerly known as inner again, it's going to say sorry, counter is now one in the backpack, you can't run me again. But it's gonna be really interesting interweaving here.

[00:04:55] So I said we're looking for another way. We're gonna map this out in full, but let's look at another way. Our oncified multiply by two is going to be the inner function that comes out of oncify. It's going to appear to edit multiply by two. It ain’t. You can't edit a function.

[00:05:12] It's gonna appear to give multiply by two, you know, we could even actually have oncify multiply by two be given a name, I don't know, multiply by two once or whatever. It's gonna appear to edit multiply by two, it's not. In reality, what is it doing? It's creating a new function that does have access to a backpack.

[00:05:34] We need a backpack to be able to limit a function to run only once. I should have stressed that. A function to run once and limited to only run once needs to remember it's previously been run. Otherwise, how can it be limited to run only once? A normal function doesn't remember its previous running.

[00:05:50] So it doesn't know it's been run before. So we need our function to have a backpack. And this is exactly what's gonna happen here. But we can't give multiply by two a backpack later. So we're instead going to decorate it. Which in the land of functional programming means creating a brand new function called inner inside of oncify, inside of which we're going to check a counter, which is going to have access to a persistent counter in the backpack after the first running of inner notice oncify multiple by two.

[00:06:23] We're going to not be able to run convert me, which is gonna be multiply by two, again. This, people, is using closure, the principle of giving functions permanent memories, to supercharge our functions, to add new functionality to our function multiply by two once it's been initially saved. And it turns out to be a core principle of functional programming.

[00:06:52] Beyond this, folk, once you realize that you can have your function, be pseudo-edited by building a brand new function inside of which it's going to run the function that's passed to the function oncify that produces a brand new function. Once you realize that, you may not just wanna store in the backpack a counter, for example.

[00:07:18] You may actually want to store an input for a function that requires two inputs. Knock that one out, and now the function only requires one input. Which might start finally, to solve Seth's worry. That when I list all functions, when my dream of functional programming is listing off my functions, do this one, then this one, then this one automatically.

[00:07:42] With point free style. No reference to the running of them, no putting the parens on and saying what to take as the input. So if my function that I'm taking into my list of functions to run one after another after another requires two inputs, it's gonna break my whole setup.

[00:07:55] We'll see all that in a moment. For now, here we go, people. We are going to build a new, apparent, a pretend multiply by two function that works just like multiply by two, but actually is a totally different function that happens to run multiply by two inside of itself.

[00:08:14] And we're gonna keep that multiply by two function inside oncify multiply by two inside of its backpack.