Skip to content

Instantly share code, notes, and snippets.

@suissa
Created October 2, 2017 23:55
Show Gist options
  • Save suissa/d4d5ee092efc45a93b69d3d450971476 to your computer and use it in GitHub Desktop.
Save suissa/d4d5ee092efc45a93b69d3d450971476 to your computer and use it in GitHub Desktop.
Gerenciando estruturas infinitas com Streams - Prog. Funcional de verdade com JS
// A definição de um stream se dá inicio com o uso do construtor [Stream]
// que recebe como único parâmento uma fonte que é o gerador.
// Por meio de técnicas compositivas fluídas é que se define uma cadeia
// de composição funcional. As operações de composição são [map]
// [reduce] e [filter], versão unitária das funções sobre vetores
// e [skip] e [take] que permite saltar ou recoletar n elementos
// que passam pela cadeia de composição.
// Fonts:
// https://sites.ualberta.ca/~jhoover/325/CourseNotes/section/Streams.htm
// http://blog.jeremyfairbank.com/javascript/functional-javascript-streams-2/
(function (/* Stream */) {
var map = function (fn) {
return function () {
return fn.apply (null, arguments);
};
};
var reduce = function (fn, b) {
var ac = b;
return function () {
var args = [].slice.call (arguments);
ac = fn.apply (null, [ac].concat (args));
return ac;
};
};
var filter = function (fn) {
return function () {
var out = fn.apply (null, arguments);
if (out) return arguments [0];
};
};
var take = function (n) {
var v = [];
return function (x) {
v.push (x);
if (v.length > n) {
var w = v.concat ([]);
v = [];
return w;
}
};
};
var skip = function (n) {
var i = 0;
return function (x) {
i++;
if (i > n) return x;
};
};
var fluent = function (hn) {
var cb = hn || function () {};
return function (fn) {
return function () {
cb (fn.apply (null, arguments));
return this;
};
};
};
var sequenceBreakWith = function (fns) {
return function (data) {
return fns.reduce (function (ac, fn) {
return ac === void 0 ? void 0 : fn (ac);
}, data());
};
};
var Stream = function (source) {
var fns = [];
var define = fluent (function (fn) {
fns.push (fn);
});
var next = function (fns, data) {
var result = sequenceBreakWith (fns)(data);
return result !== void 0 ? result : next (fns, data);
};
return {
map : define (map),
filter : define (filter),
reduce : define (reduce),
take : define (take),
skip : define (skip),
end : function () {
return {
next: function () {
return next (fns, source);
}
};
}
};
};
(function (/* Evens */) {
var inc = function (x) { return x + 1; };
var evn = function (x) { return x % 2 === 0; };
var source = (function (fn, b) {
var c = b;
return function () {
return (c = fn (c));
};
})(inc, 0);
var evens = Stream (source)
.skip (10)
.map (inc)
.filter (evn)
.take (5)
.end ();
console.log (
evens.next (), // [ 12, 14, 16, 18, 20, 22 ]
evens.next (), // [ 24, 26, 28, 30, 32, 34 ]
evens.next () // [ 36, 38, 40, 42, 44, 46 ]
);
})();
(function (/* Primes */) {
var inc = function (x) { return x + 1; };
var prime = function (x) {
return (function primeAux (x, d) {
return d > Math.sqrt (x) ? true :
x % d === 0 ? false :
primeAux (x, d+1);
})(x, 2);
};
var source = (function (fn, b) {
var c = b;
return function () {
return (c = fn (c));
};
})(inc, 0);
var primes = Stream (source)
.skip (2)
.map (inc)
.filter (prime)
.take (10)
.end ();
console.log (
primes.next (), // [ 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41 ]
primes.next (), // [ 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89 ]
primes.next () // [ 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149 ]
);
})();
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment