Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // =============== NOTE ===============
- // The implementations below use the term "Iterable" for any value
- // which can be iterated and includes all of the following:
- // - Array a :: Arrays containing any type
- // - Generator a :: Generators returning any type
- // - Iterator a :: Iterators returning any type
- /********** ARITY FUNCTIONS **********/
- const monadic = (f) => (a) => a === void 0 ?
- monadic(f) :
- f(a);
- const dyadic = (f) => (a, b) => a === void 0 ?
- dyadic(f) :
- b === void 0 ?
- monadic((_b) => f(a, _b)) :
- f(a, b);
- const triadic = (f) => (a, b, c) => a === void 0 ?
- triadic(f) :
- b === void 0 ?
- dyadic((_b, _c) => f(a, _b, _c)) :
- c === void 0 ?
- monadic((_c) => f(a, b, _c)) :
- f(a, b, c);
- /********** STREAM FUNCTIONS **********/
- // Takes an iterable collection and turns it into a stream
- // toStream :: Iterable -> Iterable
- const toStream = monadic((xs) => (function * (a) { yield * a; })(xs));
- // Takes start, stop and step arguments and returns an iterable
- // which returns values until stop is reached. All arguments are optional
- // and should be numeric values. If no arguments are given, the resulting
- // iterable goes on forever
- // range :: Number?, Number?, Number? -> Iterable
- const range = (start = 0, end = Infinity, step = 1) => (function * (a, b, c) {
- let d = a; while (d < b) { yield d; d += c; }
- })(start, end, step);
- // Takes a variadic number of iterable collections and chains them
- // into a single iterable
- // chain :: Iterable1 ... IterableN -> Iterable
- const chain = (...xs) => (function * () {
- for (let x of xs) { for (let y of x) { yield y; } }
- })();
- // Takes a reducer function, a seed value and an iterable collection
- // and folds/reduces the collection into the seed value.
- // Note: This function returns a final value which might not be iterable!
- // fold :: (a, b -> a) -> a -> Iterable -> a
- const fold = triadic((fn, seed, xs) => (function * (a, b, c) {
- let d = b; for (let e of c) { d = a(d, e); } yield d;
- }(fn, seed, xs)));
- // Takes a mapping function and an iterable collection and maps the
- // function over each item in the collection
- // map :: (a -> b) -> Iterable -> Iterable
- const map = dyadic((fn, xs) => (function * (a, b) {
- for (let c of b) { yield a(c); }
- }(fn, xs)));
- // Takes a predicate function and a iterable collection and filters
- // all values which satisfy the predicate
- // filter :: (a -> Boolean) -> Iterable -> Iterable
- const filter = dyadic((fn, xs) => (function * (a, b) {
- for (let c of b) { if (a(c)) { yield c; } }
- }(fn, xs)));
- // Takes a number N and an iterable collection and takes N items
- // from the collection
- // take :: Number -> Iterable -> Iterable
- const take = dyadic((n, xs) => (function * (a, b) {
- let c = 0; for (let d of b) { if (c < a) { c += 1; yield d; } else { break; } }
- })(Math.abs(n), xs));
- // Takes a predicate function and an iterable collection and
- // returns items as long as the predicate is satisfied
- // takeWhile :: (a -> Boolean) -> Iterable -> Iterable
- const takeWhile = dyadic((fn, xs) => (function * (a, b) {
- for (let d of b) { if (fn(d)) { yield d; } else { break; } }
- })(fn, xs));
- // Takes a number N and an iterable collection and drops the first
- // N items from the collection
- // drop :: Number -> Iterable -> Iterable
- const drop = dyadic((n, xs) => (function * (a, b) {
- let c = a; for (let d of b) { if (c > 0) { c -= 1; continue; } else { yield d; } }
- })(Math.abs(n), xs));
- // Takes a predicate function and an iterable collection and
- // drops items as long as the predicate is satisfied
- // dropWhile :: (a -> Boolean) -> Iterable -> Iterable
- const dropWhile = dyadic((fn, xs) => (function * (a, b) {
- for (let c of b) { if (!a(c)) { continue; } else { yield c; } }
- })(fn, xs));
- // Takes an iterable collection and skips all items which are either
- // undefined or null
- // keep :: Iterable -> Iterable
- const keep = monadic((xs) => (function * (a) {
- for (let b of a) { if (b != null) { yield b; } }
- })(xs));
- // Takes a number N and an iterable collection and partitions the
- // collection into arrays of N items each
- // partition :: Number -> Iterable -> Iterable
- const partition = dyadic((n, xs) => (function * (a, b) {
- let c = []; for (let d of b) { if (c.length >= n) { yield c; c = [d]; } else { c.push(d); } }
- yield c;
- })(n, xs));
- // Takes a function and an iterable collection and partitions the
- // collection into arrays each time the function returns a new result
- // partitionWith :: (a -> a) -> Iterable -> Iterable
- const partitionWith = dyadic((fn, xs) => (function * (a, b) {
- let c = [], e, f;
- for (let d of b) { e = a(d); if (f === void 0 || e === f) { c.push(d); } else { yield c; c = [d]; } f = e; }
- yield c;
- })(fn, xs));
- // Takes an iterable collection and returns only unique items of it
- // unique :: Iterable -> Iterable
- const unique = monadic((xs) => (function * (a) {
- let b = Object.create(null); for (let c of a) { if (b[c] === void 0) { b[c] = c; yield c; } }
- })(xs));
Add Comment
Please, Sign In to add comment