Use Transducers in Production

Paul Frend
InstructorPaul Frend
Share this video with your friends

Social Share Links

Send Tweet
Published 7 years ago
Updated 5 years ago

While it’s possible to use our transducers in production (after writing some tests!), I would recommend using a proven transducer library instead.

In this lesson, we’ll go through how to use transducers.js from James Long instead of our functions. We’ll also cover some more advanced features which we didn't add support for ourselves, like short-circuiting iterations with the take transform as well as transducing lazily over iterables.

The aim is that you’ll be able to use these libraries with more confidence and better understanding since we’ve been through how things are working under the hood.

You can also check out transducers-js by cognitect labs, which is very similar in its feature set to transducers.js. And remember, you don’t have to rely solely on the transforms in the library, you can write your own as well, as long as you support the transducer protocol.

Instructor: [00:00] Instead of using our own library, we're now importing T from transducers JS. T will just be a big object exporting all the functions of the library. We've also got the same double and even transform from previous lessons only now we're calling filter, map, and compose off of the transducers JS library.

[00:20] One of the biggest features we didn't add support for when building up our own transducers was short circuiting. Let's start by using this double and even transform under regular array. Let's define an array from 1 to 10. We'll call that R. We'll just fill that with 10 numbers. Let's build up a result by calling seek. We'll call T.seek. I'll pass in R. Then we'll just pass in our double and even transform.

[00:49] This is almost the same API as ours expect it takes the collection first whereas our version of seek took the transform first and then we passed the collection. Let's just verify our results. We have our expected outcome.

[01:05] To add short-circuiting to this, we do that with the take operation. Let's compose double and even with take. We'll take only the first two elements. Now, let's check our results again. Now we only have two entries in our result. The useful thing here though is the take only performed two iterations. It didn't return the first two entries after traversing the whole array.

[01:37] Instead, the result was returned as soon as we knew the two elements were going to be returned which, since we're filtering even numbers, would have been the first four elements to give us two and four which we then double to give us four and eight.

[01:52] Now if we look at the source of take, we can see how this works. I'm just going to drill in here. If we look at the step operation of take, which if you remember happens in each iteration, you see we've got this check where the number we passed when we called take which is stored under this.n. If the amount of iterations is greater or equal to this, then we're calling this ensure reduced on the result.

[02:17] If we look at that, it's going to wrap our value in this reduced call. If we look at that, we can see we're extending the transducer protocol with this reduced value. That can then be used by other functions to see if we should continue iterating or not.

[02:33] We can also transduce lazily over iterators. We can either pass an iterator in and start collection here or transducers JS also has an iterator helper which will convert it for you. Let's wrap our array in the iterator helper which is as simple as calling T.iterator. Now if we check our result, our result is now a lazy transformer which is a data structure transducers JS provides.

[03:00] On this lazy transformer, we can call next. If we run our results again, we see we get an object with the value four and a down key with the value of false. Our result is now an iterable which we can keep calling next on. We're in complete control of the production of values. They all pass through our compose transforms.

[03:22] Since we're using take two, when we call next our third time, we see that our result doesn't have a value but down is now true. In a similar fashion, we can also use the output of a generator function as our collection. Let's delete this. We'll define make numbers. It's going to count up from the number one. Then we can use this as our collection as calling it will return an iterable.

[03:51] Let's save our result to lazy nums. That will again be equal to seek. There's our collection we'll call make numbers. Our transform will just be double and even. Like before, we can call this lazily whenever we want to consumer another value. Let's add in a few calls to next.

[04:11] Let's call this three times and verify our result. We get 4, 8, and 12. Bit down will now never be true since we're not short-circuiting anymore. We can call this as many times as we want.

[04:25] There's plenty more you can do with transducers. Check out the library docs and start playing around. If you come across some other cool use cases or integrations, please share them in the comments. With that in mind, you should now have a solid understanding of the inner workings of transducers so that you can use them more effectively in your applications.

Bijoy Thomas
Bijoy Thomas
~ 6 years ago

Excellent course!

The short circuiting is awesome but somehow the types in the composition below seems a little odd.

doubleAndEven = t.compose(t.filter(isEven), t.map(double))

t.compose(doubleAndEven, t.take(2))

The doubleAndEven returned from the t.compose has transformations on numbers, which is then further composed with t.take which looks like a transformation on a list. I guess the way to look at it is that the type of t.whatever functions are reducers which can be composed

Markdown supported.
Become a member to join the discussionEnroll Today