This course has been updated! We now recommend you take the Functional-Light JavaScript, v3 course.
Transcript from the "Fusion" Lesson
[00:00:00]
>> Kyle Simpson: So what we just described was, and what we just walked through with exercise seven was a series of steps. Where we had these methods that were producing an iteration across the list and doing something to it. And then that produced a new list, and we iterated over that list, and then that produced a list, and then we iterated over that list.
[00:00:21] As you start modeling more of your code around list operations, you end up oftentimes coming up with, for example, three different map functions adjacent to each other in a chain of operations. And if we look at that list of map calls, the map(add1), map(mul2), and map(div3), the good part about it is it's very clear.
[00:00:44] Step one is to add 1 to each of the items. Step two is to multiple them by 2. Step three is to divide them by 3, that part is very clear. But the part that can be potentially negative here, is a performance aspect, because we're looping over the entire list every time.
[00:01:05] If that was a big list that could be a problem. But there's a deeper problem here which is even less obvious, which is that we're creating a whole new intermediary array every time. So now we're gonna be, if that list was large, we'd be tripling the size of our memory usage just because every time we produce a mapping, we've produced a new array.
[00:01:25] These aren't mutating our same array in place.
>> Kyle Simpson: For that reason, for performance and memory usage reasons, and also just from the perspective of, there's some repetition here. I'm having to repeat a .map call over and over. We could ask ourselves, is there some way that I could may be express that as single map call?
[00:01:46] Which is exactly what that question a little while ago was asking, is there some way to compose these together? We'll let's think about the shape of add1, mul2 and div3. They each take a value in, do some transformation on it, and return a value of like kind out.
[00:02:06] Does that shape sound compatible for those functions to compose together?
>> Speaker 2: Yep.
>> Kyle Simpson: Yep, so fusion is when we take a series of adjacent list operations, whether they're methods or just actual standalone function calls. Take a series of list operations, and compose those utilities into a single operator, and then run that once across the list.
[00:02:34] In general, that's what fusion is called. And when those operator functions have the same shape, compose is all we need to do to do the fusion. So if I had a compose utility that could take any number of operations, any number of functions, rather, then we could just simply call compose.
[00:02:54] Remember, compose works right to left, so we'd have to list add1 on the right, so we'd have to list them in reverse order. We'd have to say compose div3, mul2, add 1, or we'd have to use pipe if we wanted to go in this order. But I wanna push this even one step further and say, you might remember, early in the class, we had a compose2, and compose2 could only compose two functions together.
[00:03:19] So what if that's all we had, what if we didn't have the general compose? And we only had something that could compose two functions together. Well, if we want to compose a list of functions, and all we have is a function that can take two values together, do we know about a list operation that helps with things like that?
[00:03:39]
>> Speaker 2: Reduce.
>> Kyle Simpson: Reduce. Reduce takes a function that's shaped where it takes two things and makes them into one, reduce can do that across a list. So if only had a composeRight utility that could only do two of them, we could represent that composition as a reduction. So I can take that list of functions, [div3, mul2, add1], call a reduce on them with the composeRight utility to create my single composed mapper function that I then run across the list just once.
[00:04:19]
>> Kyle Simpson: Part of becoming a functional programmer is developing the instincts to ask questions like I just asked. Wait a minute, what if all I have is the compose of two utilities, what does that look like? I recognize that's a reduction, that's a reduce. And that again is why I said earlier that reduce is our Swiss Army knife.
[00:04:39] And when we ask this question, we end up saying wow, I can solve that with reduce and I can solve that with reduce. Or I can solve that with composition, or I can solve that with currying. You just wanna start to develop that instinct to say, what do I need here?
[00:04:53] I know what that looks like, this is what I need. So that's fusion, and it works well when the shape of those adjacent operators is compatible. But if we had a map, a filter, and a reduce sitting next to each other, the shapes aren't compatible, like was just asked about in our exercise.
[00:05:15] Those shapes aren't compatible, so if we wanted to do fusion there, we gonna need a more sophisticated technique. And that sophisticated technique is called transducing.