Make an Into Helper to Remove Boilerplate and Simplify our Transduce API

Paul Frend
InstructorPaul Frend
Share this video with your friends

Social Share Links

Send Tweet
Published 7 years ago
Updated 6 years ago

Our transduce function is powerful but requires a lot of boilerplate. It would be nice if we had a way to transduce into arrays and objects without having to specify the inner reducer behaviour, i.e. how to build up values, since a given collection type will almost always have the same inner reducer.

In this lesson we'll being doing just that with an into() helper function that will know if an array or object collection is passed in and handle each case accordingly.

Instructor: [00:01] The purpose of into helper is to figure out which inner reducer to use based on the collection type of our output. We want to be able to call into with our target collection, our transform, and the source collection.

[00:16] Notice that we're not specifying this reducer anywhere. That's what we want into to figure out by itself. Let's try and create this. We'll define into, which will take to as our target, our transform, and our collection.

[00:33] Then in here, we just want to call transduce based on this collection type. We can start by checking if it's an array. If it is an array, then we'd want to call transduce with the transform, an array reducer, our target collection as our initial seed, and our collection as our source.

[00:54] If you recall, the push reducer just takes an accumulation and a value, the accumulation being our array, pushes on the value, and returns the accumulation. We also need to handle the case where our target collection is an object. Let's check for that.

[01:10] We're going use the isPlaying object helper from Lodash here, just because doing that ourselves is nontrivial. If it is, we'll again call transduce with our transform. In here, we'll need some object reducer. Our target collection will be our seed, and we'll pass the collection as our source.

[01:32] Finally, if neither of those conditions match, let's just throw an error. We'll say just into only supports arrays and objects as to. Now, we need to define this object reducer. Let's do that up here.

[01:49] That will take some object and a value. Let's treat this as a value is an object with keys and values, and we want those keys and values to be folded into this accumulation object. To accomplish that, let's just do a shallow merge.

[02:10] That should be everything we need. Let's start by testing it out on an array. I will call into with an array as our target. For our transform, let's create a simple operation which multiplies array values by 10, and then divides them by two.

[02:27] I'll call compose, and we want two map operations. The first one, dividing by two, and the second one, multiplying by 10. Let's make this a bit more readable. For our target collection, let's just use an array with a few numbers.

[02:46] Let's check our result. We get an array with 5, 10, 15, 20. Perfect. Let's also test our object support, and build up an object with matching keys and values from an array. We'll call into again. Our target is going to be an object. We want to transform to convert values into objects.

[03:05] That will be a map operation, which will take a value and return an object with both the key and the values as value from the array. Again, an array of numbers is our source. We can see we forget a return up here. Let's add that in.

[03:22] Now, let's give this a go. As expected, we get this object back, where the keys and values match each other. Let's also filter out any array values that aren't numbers. Let's say we've got the string hello in here, and a function returning the string, world.

[03:39] We don't get an error, since in JavaScript, we can actually have functions as keys. For our purpose here, we're just interested in the numbers. Let's add that into our transform. We'll add in a call to compose, and then I'm just going to filter to only include numbers.

[03:57] This works straight away, because we're already importing isNumber from Lodash. To recap, our into helper now lets us transduce into both arrays and objects without specifying our inner reducers.

Bijoy Thomas
Bijoy Thomas
~ 7 years ago

Hey Paul, right about 4:06 into the video (when you say "to recap..."), the order of the composition changes to compose(map(), filter()) when it should be compose(filter(), map()). The former ordering will return an empty object since it will fail the filter prediacte.

Briisk Sp. z o.o.
Briisk Sp. z o.o.
~ 7 years ago

Hey Paul, right about 4:06 into the video (when you say "to recap..."), the order of the composition changes to compose(map(), filter()) when it should be compose(filter(), map()). The former ordering will return an empty object since it will fail the filter predicate.

That's right, I noticed the same. And I also noticed that when used as a transformer the compose function works like the pipe and vice-versa. Composed functions get called normally from right to left but in this case it's from left to right, that took me a while to sink in :-D

Paul Frend
Paul Frendinstructor
~ 7 years ago

@Briisk @Bijoy Thanks for spotting the mistake guys. I recorded it the wrong way around first and then re-recorded the visuals that showed that bit, but must have missed the last few seconds. Sorry about that.

At least the code sample is correct :)

Markdown supported.
Become a member to join the discussionEnroll Today