Sample Video Frame
29: Partial Application
In the previous exercise when you created the closure you also accidentally used something called "partial application". Sometimes this is also called "currying" but others are subtle distinctions between the two which I won't get into in this exercise. Frankly JavaScript isn't strong enough of a functional programming language to even bother with this distinction.
In partial application you create a function that already has one half of the calculation ready to go, and then use that function with other functions to complete the calculation. In the previous exercise you did this by establishing the left side of an addition, and then when you called the function you gave it the right hand side to complete the calculation. This is useful because there are functions that only receive limited parameters, but you have to change how they work or add another parameter to complete a calculation. With partial application you simply create a new function that "eats" some of the parameters.
In this exercise I'm going to use partial application, combined with data transformations to create a useful function called the tee
. This function works like a pipe in your plumbing which takes the water coming in and sends it out to two different directions. You could also call this a "fork" but that is confused with existing operations called fork in other contexts. In this case I'm using plumbing as my model for this function.
You can use this technique when you want to capture the result of a calculation in the middle of a chain of transformation calls. Partial application isn't limited to only this, but I find this is the most direct and useful way to use it.
The Code
Most of this code you've already seen from the previous pets demos so now I'm just adding the
tee
function builder to allow you to craft your own tee operation.
let pets = [
{name: 'Yeller', type: 'Dog', age: 12},
{name: 'Akumano', type: 'Japanese Bobtail Cat', age: 2},
{name: 'Meaw Peesard', type: 'Siamese Cat', age: 100},
{name: 'James', type: 'Gecko', age: 2},
]
const young_pets = (pet) => {
return pet.age <= 10;
}
const age_pets = (pet) => {
return [pet.name, pet.age + 10];
}
const name_age = (pet) => {
return `${pet[0]} is ${pet[1]}`;
}
const debug = (msg) => {
console.log(msg);
return msg;
}
const tee = (result, data, cb) => {
const side = (input) => {
cb(input, result, data);
return input;
}
return side;
}
let owned_pets = [];
const add_owner_tee = tee(owned_pets, 'Zed', (i, r, d) => {
r.push({pet: i, owner: d});
});
let age_young_animals = pets.filter(young_pets)
.map(add_owner_tee)
.map(age_pets)
.map(name_age);
console.log("-- Pets with Owners:");
owned_pets.forEach(debug);
console.log("-- Young Animals:");
age_young_animals.forEach(debug);
I will warn you that while functional programming is very simple, it can quickly become incredibly convoluted and indirect. You should study this code as an example of the very edge of complicated code in the functional style, but keep in mind that it gets much more complicated than this. Thankfully JavaScript is so terrible at functional programming that you won't see too many people abusing it.
What You Should See
As usual when you run this code you should see this:
$ node "code.js"
-- Pets with Owners:
{
pet: { name: 'Akumano', type: 'Japanese Bobtail Cat', age: 2 },
owner: 'Zed'
}
{ pet: { name: 'James', type: 'Gecko', age: 2 }, owner: 'Zed' }
-- Young Animals:
Akumano is 12
James is 12
You should definitely watch the video for this exercise as I give a visual depiction of how this function works to allow you to do this.
Learn JavaScript Today
Register today for the Early Access course and get the all currently available videos and lessons, plus all future modules for no extra charge.
Still Not Sure? Try the next FREE Lesson!