September 22nd, 2014
In Technology
No Comments
If you enjoy this article, see the other most popular articles
If you enjoy this article, see the other most popular articles
If you enjoy this article, see the other most popular articles
Transducers in Javascript
(written by lawrence krubner, however indented passages are often quotes). You can contact lawrence at: lawrence@krubner.com, or follow me on Twitter.
This is an interesting sentence:
The reduce function is the base transformation; any other transformation can be expressed in terms of it (map, filter, etc).
All of the programming languages seem to be adding all of the same features. Over the last 2 years, suddenly people woke up and realized they could escape “callback hell” by using finite state machines to enable a pleasant API for async programming, core.async being a good Clojure example.
Now James Long adds transducers to Javascript:
Let’s play around with all the kinds of data structures we can use now. A type must at least be iterable to use with into or transduce, but if it is also buildable then it can also be used with sequence or the target collection of into.
var xform = compose(map(x => x * 2),
filter(x => x > 5));// arrays (iterable & buildable)
sequence(xform, [1, 2, 3, 4]);
// -> [ 6, 8 ]// objects (iterable & buildable)
into([],
compose(map(kv => kv[1]), xform),
{ x: 1, y: 2, z: 3, w: 4 })
// -> [ 6, 8 ]sequence(map(kv => [kv[0], kv[1] + 1]),
{ x: 1, y: 2, z: 3, w: 4 })
// -> { x: 2, y: 3, z: 4, w: 5 }// generators (iterable)
function *data() {
yield 1;
yield 2;
yield 3;
yield 4;
}into([], xform, data())
// -> [ 6, 8 ]// Sets and Maps (iterable)
into([], xform, new Set([1, 2, 3, 3]))
// -> [ 6 ]into({}, map(kv => [kv[0], kv[1] * 2], new Map([[‘x’, 1], [‘y’, 2]])))
// -> { x: 2, y: 4 }// or make it buildable
Map.prototype[‘@@append’] = Map.prototype.add;
Map.prototype[‘@@empty’] = function() { return new Map(); };
Set.prototype[‘@@append’] = Set.prototype.add;
Set.prototype[‘@@empty’] = function() { return new Set(); };sequence(xform, new Set([1, 2, 3, 2]))
sequence(xform, new Map([[‘x’, 1], [‘y’, 2]]));// node lists (iterable)
into([], map(x => x.className), document.querySelectorAll(‘div’));
// custom types (iterable & buildable)
into([], xform, Immutable.Vector(1, 2, 3, 4));
into(MyCustomType(), xform, Immutable.Vector(1, 2, 3, 4));// if implemented append and empty:
sequence(xform, Immutable.Vector(1, 2, 3, 4));// channels
var ch = chan(1, xform);
go(function*() {
yield put(ch, 1);
yield put(ch, 2);
yield put(ch, 3);
yield put(ch, 4);
});go(function*() {
while(!ch.closed) {
console.log(yield take(ch));
}
});
// output: 6 8Now that we’ve decoupled the data that comes in, how it’s transformed, and what comes out, we have an insane amount of power. And with a pretty simple API as well.
Did you notice that last example with channels? That’s right, a js-csp channel which I introduced in my last post now can take a transducer to apply over each item that passes through the channel. This easily lets us do Rx-style (reactive) code by simple reusing all the same transformations.
A channel is basically just a stream. You can reuse all of your familiar transformations on streams. That’s huge!
February 8, 2022 9:33 am
From Michael S on How I recovered from Lyme Disease: I fasted for two weeks, no food, just water
"Did you have Bartonella, too? Seems it uses autogenesis..."