step
function, and returns a new step
function. stepā° ā step¹
step
function, in turn, accepts the current result and the next element, and should return the new current result. In this case, the data type of the current result is not specified. resultā°, item ā result¹
step¹
function, you need to call the stepā°
function, passing in it the old current result and the new value that we want to add. If we do not want to add a value, then simply return the old result. If we want to add one value, then we call stepā°
, and then what it returns will return as a new result. If we want to add several values, then we call stepā°
several times along the chain, this is easier to show in the example of the implementation of the flatten transducer: function flatten() { return function(step) { return function(result, item) { for (var i = 0; i < item.length; i++) { result = step(result, item[i]); } return result; } } } var flattenT = flatten(); _.reduce([[1, 2], [], [3]], flattenT(append), []); // => [1, 2, 3]
step
several times, each time saving the current result to a variable, and passing it the next time you call it, and at the end return the final one.step
function calls another, and that next one, and so on until the last service step
function, which already saves the result to the collection ( append
from the first part). function Reduced(wrapped) { this._wrapped = wrapped; } Reduced.prototype.unwrap = function() { return this._wrapped; } Reduced.isReduced = function(obj) { return (obj instanceof Reduced); } function take(n) { return function(step) { var count = 0; return function(result, item) { if (count++ < n) { return step(result, item); } else { return new Reduced(result); } } } } var first5T = take(5);
result
as usual, we return the result
wrapped in Reduced
. Immediately update the step function signature: resultā°, item ā result¹ | reduced(result¹)
_.reduce
function _.reduce
no longer be able to handle this version of the transducer. We'll have to write a new one. function reduce(coll, fn, seed) { var result = seed; for (var i = 0; i < coll.length; i++) { result = fn(result, coll[i]); if (Reduced.isReduced(result)) { return result.unwrap(); } } return result; }
first5T
transducer. reduce([1, 2, 3, 4, 5, 6, 7], first5T(append), []); // => [1, 2, 3, 4, 5]
Reduced.isReduced(result)
test to transducers that call step several times (note flatten). Those. if in flatten, if we call step step, the result wrapped in Reduced will be returned to us, we must complete our loop, and return this wrapped result. function transduce(transducer, append, seed, coll) { var step = transducer(append); // . // step , // (step) // , . return reduce(coll, step, seed); } transduce(first5T, append, [], [1, 2, 3, 4, 5, 6, 7]); // => [1, 2, 3, 4, 5]
function step(result, item) { if (arguments.length === 2) { // // step(result, item) } if (arguments.length === 1) { // // step c , . // - , // step , . // return step(result); // - result = step(result, -); return step(result); } }
resultā° ā result¹ * resultā°, item ā result¹ | reduced(result¹) * reduced(result¹), . .
transduce()
and append()
functions will have to be updated to add support for the final call. function transduce(transducer, append, seed, coll) { var step = transducer(append); var result = reduce(coll, step, seed); return step(result); } function append(result, item) { if (arguments.length === 2) { return result.concat([item]); } if (arguments.length === 1) { return result; } }
function partition(n) { if (n < 1) { throw new Error('n 1'); } return function(step) { var cur = []; return function(result, item) { if (arguments.length === 2) { cur.push(item); if (cur.length === n) { result = step(result, cur); cur = []; return result; } else { return result; } } if (arguments.length === 1) { if (cur.length > 0) { result = step(result, cur); } return step(result); } } } } var by3ItemsT = partition(3); transduce(by3ItemsT, append, [], [1,2,3,4,5,6,7,8]); // => [[1,2,3], [4,5,6], [7,8]]
reduce
, and then to transduce
.)step
function. ā result resultā° ā result¹ resultā°, item ā result¹ | reduced(result¹)
transduce()
and append()
functions. function transduce(transducer, append, coll) { var step = transducer(append); var seed = step(); var result = reduce(coll, step, seed); return step(result); } function append(result, item) { if (arguments.length === 2) { return result.concat([item]); } if (arguments.length === 1) { return result; } if (arguments.length === 0) { return []; } }
function map(fn) { return function(step) { return function(result, item) { if (arguments.length === 2) { return step(result, fn(item)); } if (arguments.length === 1) { return step(result); } if (arguments.length === 0) { return step(); } } } }
transduce()
parameter inside append()
, at first glance this is an unnecessary action, but it gave us the opportunity to create transducers that add something to the beginning of the collection (just like the ones that add to the end, just the opposite) .Source: https://habr.com/ru/post/237733/
All Articles