Transcript from the "Deriving Transduction: Combiner & Currying" Lesson
>> Kyle Simpson: All right, so this next step, this is one of those out of thin air, how would you have ever imagined to do this. The inside of each of those reducers, that is lines 3 and 4, and lines 10 and 11. I want you to look very closely at those two sets of lines.
[00:00:18] And I want you to see that there is something very similar about those lines.
>> Kyle Simpson: Do you see that in both pairs of lines in line 3 and 4 and in line 10 and 11 in both cases, what fundamentally happens is a value and an array get reduced into a new array.
[00:00:42] That is, that we push a value into an array and then we return it.
>> Kyle Simpson: There is definitely the if statement, and there is definitely the mapping, but abstract with there we see that there's something generic occurring, which is take a value in an array and reduce them combine them together into a new array, or an extended array rather.
[00:01:06] Okay, here's what we're gonna do, we're gonna factor out that whole genericism part. We're gonna say, that taking an array and the value and combining them, we're gonna make a combiner, and we are gonna use that combiner in both of these reducers. We are gonna do some drying, if you will, right?
[00:01:26] Take those parts that are the same out and use that combiner. So here's how we are gonna do that. Up on the top, line 1 through 4, I have my list combination function, it is a combiner. Look at the shape of it. It takes two values and produces one value as a return.
[00:01:44] What shape is that?
>> Speaker 2: Reducer.
>> Kyle Simpson: It's just a reducer, right? It is the shape of a reducer. It takes two values and reduces them into one. In this case, the kind of reduction that it's doing is value into an array. But we've seen lots of other reducers like two numbers being added together or two strings being concatenated.
[00:02:06] This is just a different kind of reduction. Is a reduction between an array and a value, okay? So temporarily, we've got this standalone function called list combination and it definitely has that side effect thing in it. Doesn't it? Is doing list that push instead of making a new list and concatenated on to the end of the list.
[00:02:27] It's modifying list by reference. And that is definitely a bad idea from the general perspective. But we're just gonna hold this for one couple more steps and then it's not gonna matter, okay? Let's look at how we're using that utility. Look at lines 8 and 14. On line 8 and line 14, we're just simply deferring to that list combination function to do its work.
[00:02:52] We're simply passing a long list and the value to push into it on line 8. And then on line 14, we are only calling list combination if the if statement passed. But we're letting list combination handle the details of deciding how to take an array and a value and put them together.
>> Kyle Simpson: Everybody with me?
>> Kyle Simpson: So look down at the bottom, lines 22 through 24, they haven't changed at all. All we've done now is factor out that idea of taking an array, and a value and putting them together. We've factored that out as a generic kind of reducer.
[00:03:32] Another one of those that would have never occurred to me, where did that come from? Is that we could observe that even though our reducers are hard coded to list combination, that's only one kind of possible way that combination might occur.
>> Kyle Simpson: We might want to parameterize the combiner function.
[00:03:57] We might want to be able to provide that combiner function as an argument.
>> Kyle Simpson: So we're gonna do one more step of obstruction which is to add one more layer of function wrapping here where before we even provide the mapping function, we provide the combiner to use in the reducer, okay?
[00:04:20] So, here's what that looks like. We have a map producer that is expecting a mapping function and a combiner and I've done it with a curry. So look how the map producer is expecting two inputs, but I've made it a curried function.
>> Kyle Simpson: And look how filter reducers is expecting a predicate and a combiner, but I've made it a curried function, specifically it's waiting for two inputs.
[00:04:49] So look down on line 22, you can see that add one, when I call map producer with add one it's coming in as the first of these inputs. It's coming in as the input for mapping function. And on line 23, when I say is odd, that one is going to come in as predicate function.
[00:05:10] And map producer of add one is returning us a new function, an intermediate function, which is waiting for what? What are we going to pass to it?
>> Kyle Simpson: We're gonna pass to it a combiner. We're gonna pass to it a reducer. So map reducer with add one has returned to us a high order reducer, a proto-reducer, right?
[00:05:38] It's a thing that will make a reducer if provided a combiner, aka, another reducer. And the same is true with filter reducer that when we pass in is odd we get back that intermittently function that's waiting combine function, and then we pass in list combination for it.
>> Kyle Simpson: So rather than having it hard coded, we've just now made it a thing that we can pass along.
>> Kyle Simpson: We still have fundamentally three reduced cost, okay? I know it feels like when are we ever gonna make progress, but it's very incremental here, right? I'm showing you each of the steps of the thinking. And I couldn't even begin to show you the mathematical steps, but I can at least kind of explain to you how these programming steps are working out.
[00:06:25] How you might if potentially come up with the idea that I would abstract out a generic detail into something I pass in, right? We've done that kinda thing in programming before, and that's essentially what is happening here. Did you have a question?
>> Speaker 3: Yes, we just wanted to ask about curry and why it was taking two arguments.
>> Kyle Simpson: So curry needs to know how many arguments it's expecting to wait for, cuz it can't always determine how many arguments you are expecting. So by passing the number two, we're saying make me a function that's gonna wait until it gets two inputs. If we say curry 9 we'd have a function that would wait for nine inputs, does that make sense?
>> Speaker 3: Yes.
>> Kyle Simpson: Yeah, good question, okay? So curry here is what's allowing us to provide those separately. And that looks odd, you might say well why don't I just, if I'm calling out one in least combination I can just call it as a single function call. Why did we curry several times earlier in our course together?.
[00:07:27] What was the real benefit of doing currying?. Yes.
>> Speaker 4: To have a unitary type of function?
>> Kyle Simpson: That's true, we wanted a unitary type of function but what was that accomplishing for us. What was the whole section of that discussion talking about? Why were we doing currying or partial application?
>> Kyle Simpson: To create specialization from generalization. So we could say that now producer that takes two things is a more general function. And if I pass it the mapper or if I pass it the predicate, it becomes a more specific function doesn't it? One that only needs the combiner and that more specific function, is this transducers thing that we've been talking about this high order reducer, okay?
[00:08:11] So if we take a series of amounts, or a series of filters and turn them into transducers, that's essentially the goal. We wanna turn them into these higher order inducers, that are waiting for something like list combination to be passed in.