├── test ├── util.test.js ├── scanr1.test.js ├── flip.test.js ├── repeat.test.js ├── replicate.test.js ├── iterate.test.js ├── head.test.js ├── last.test.js ├── unzip.test.js ├── unzip3.test.js ├── map.test.js ├── unzipN.test.js ├── tail.test.js ├── reverse.test.js ├── filter.test.js ├── concat.test.js ├── init.test.js ├── cycle.test.js ├── span.test.js ├── spanInv.test.js ├── scanl1.test.js ├── splitAt.test.js ├── foldl1.test.js ├── zip.test.js ├── scanl.test.js ├── drop.test.js ├── foldr1.test.js ├── take.test.js ├── zipWith.test.js ├── foldl.test.js ├── dropWhile.test.js ├── scanr.test.js ├── takeWhile.test.js ├── foldr.test.js ├── zipWithN.test.js ├── zipN.test.js ├── zip3.test.js └── zipWith3.test.js ├── .travis.yml ├── .tern-project ├── src ├── browser.js ├── esnext │ ├── flip.js │ ├── map.js │ ├── reverse.js │ ├── filter.js │ ├── head.js │ ├── takeWhile.js │ ├── drop.js │ ├── last.js │ ├── concat.js │ ├── splitAt.js │ ├── dropWhile.js │ ├── tail.js │ ├── iterate.js │ ├── replicate.js │ ├── span.js │ ├── unzip.js │ ├── unzipN.js │ ├── scanl.js │ ├── util.js │ ├── unzip3.js │ ├── init.js │ ├── zip.js │ ├── scanl1.js │ ├── take.js │ ├── zipWith.js │ ├── spanInv.js │ ├── foldr.js │ ├── scanr.js │ ├── zipN.js │ ├── zip3.js │ ├── repeat.js │ ├── zipWithN.js │ ├── zipWith3.js │ ├── cycle.js │ ├── foldr1.js │ ├── scanr1.js │ ├── foldl.js │ └── foldl1.js ├── es5 │ ├── flip.js │ ├── head.js │ ├── replicate.js │ ├── util.js │ ├── last.js │ ├── foldr.js │ ├── scanr.js │ ├── scanr1.js │ ├── foldr1.js │ ├── foldl.js │ ├── foldl1.js │ ├── reverse.js │ ├── splitAt.js │ ├── zip.js │ ├── span.js │ ├── zipWith.js │ ├── iterate.js │ ├── spanInv.js │ ├── tail.js │ ├── zip3.js │ ├── init.js │ ├── zipWith3.js │ ├── repeat.js │ ├── zipN.js │ ├── zipWithN.js │ ├── unzip.js │ ├── unzip3.js │ ├── map.js │ ├── unzipN.js │ ├── filter.js │ ├── drop.js │ ├── takeWhile.js │ ├── dropWhile.js │ ├── scanl1.js │ ├── scanl.js │ ├── take.js │ ├── concat.js │ └── cycle.js └── index.js ├── .jsbeautifyrc ├── .gitignore ├── LICENSE ├── package.json ├── .jshintrc ├── Makefile ├── README.md └── .eslintrc /test/util.test.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/scanr1.test.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "0.10" 4 | - "0.12" 5 | script: 6 | make 7 | -------------------------------------------------------------------------------- /.tern-project: -------------------------------------------------------------------------------- 1 | { 2 | "libs":[ 3 | "ecma5", 4 | "ecma6" 5 | ], 6 | "plugins": { 7 | "node":{}, 8 | "complete_strings": {} 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/browser.js: -------------------------------------------------------------------------------- 1 | // separate into 2 files cuz https://github.com/babel/babel/issues/832 2 | 3 | require('babelify/polyfill'); 4 | 5 | module.exports = require('./'); 6 | -------------------------------------------------------------------------------- /src/esnext/flip.js: -------------------------------------------------------------------------------- 1 | // flip :: (a -> b -> c) -> b -> a -> c 2 | function flip(f) { 3 | return function(...args) { 4 | return f.call(null, args[1], args[0]); 5 | }; 6 | } 7 | 8 | module.exports = flip; 9 | -------------------------------------------------------------------------------- /src/esnext/map.js: -------------------------------------------------------------------------------- 1 | let cu = require('auto-curry'); 2 | 3 | 4 | // map :: (a -> b) -> [a] -> [b] 5 | function* map(f, a) { 6 | for (let x of a) yield f(x); 7 | } 8 | 9 | module.exports = cu(map); 10 | -------------------------------------------------------------------------------- /src/esnext/reverse.js: -------------------------------------------------------------------------------- 1 | // reverse :: [a] -> [a] 2 | // [a] should be finite 3 | function reverse(a) { 4 | let res = []; 5 | 6 | for (let x of a) res.unshift(x); 7 | return res; 8 | } 9 | 10 | module.exports = reverse; 11 | -------------------------------------------------------------------------------- /src/es5/flip.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | // flip :: (a -> b -> c) -> b -> a -> c 4 | function flip(f) { 5 | return function () { 6 | return f.call(null, arguments[1], arguments[0]); 7 | }; 8 | } 9 | 10 | module.exports = flip; -------------------------------------------------------------------------------- /src/esnext/filter.js: -------------------------------------------------------------------------------- 1 | let cu = require('auto-curry'); 2 | 3 | 4 | // filter :: (a -> Bool) -> [a] -> [a] 5 | function* filter(p, a) { 6 | for (let x of a) 7 | if (p(x)) yield x; 8 | } 9 | 10 | module.exports = cu(filter); 11 | -------------------------------------------------------------------------------- /src/esnext/head.js: -------------------------------------------------------------------------------- 1 | // head :: [a] -> a 2 | function head(a) { 3 | let first = a[Symbol.iterator]().next(); 4 | 5 | if (first.done) throw new Error('Cannot get head of empty list'); 6 | return first.value; 7 | } 8 | 9 | module.exports = head; 10 | -------------------------------------------------------------------------------- /src/es5/head.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | // head :: [a] -> a 4 | function head(a) { 5 | var first = a[Symbol.iterator]().next(); 6 | 7 | if (first.done) throw new Error("Cannot get head of empty list"); 8 | return first.value; 9 | } 10 | 11 | module.exports = head; -------------------------------------------------------------------------------- /src/esnext/takeWhile.js: -------------------------------------------------------------------------------- 1 | let cu = require('auto-curry'); 2 | 3 | 4 | // takeWhile :: (a -> Bool) -> [a] -> [a] 5 | function* takeWhile(p, a) { 6 | for (let x of a) { 7 | if (p(x)) yield x; 8 | else break; 9 | } 10 | } 11 | 12 | 13 | module.exports = cu(takeWhile); 14 | -------------------------------------------------------------------------------- /src/esnext/drop.js: -------------------------------------------------------------------------------- 1 | let cu = require('auto-curry'); 2 | 3 | 4 | // drop :: Int -> [a] -> [a] 5 | function* drop(n, a) { 6 | for (let x of a) { 7 | if (n) { 8 | --n; 9 | continue; 10 | } 11 | else yield x; 12 | } 13 | } 14 | 15 | module.exports = cu(drop); 16 | -------------------------------------------------------------------------------- /test/flip.test.js: -------------------------------------------------------------------------------- 1 | require('should'); 2 | 3 | var flip = require('../src/esnext/flip'); 4 | var div = (a,b) => a/b; 5 | 6 | describe('lazit#flip', function() { 7 | it('normal operation check', function() { 8 | var res = flip(div)(2,3); 9 | 10 | res.should.eql(1.5); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /src/esnext/last.js: -------------------------------------------------------------------------------- 1 | // last :: [a] -> a 2 | // [a] must be finite and non-empty 3 | function last(a) { 4 | if (a[Symbol.iterator]().next().done) throw new Error('Cannot get last of empty list'); 5 | if (!Array.isArray(a)) a = [...a]; 6 | return a[a.length - 1]; 7 | } 8 | 9 | module.exports = last; 10 | -------------------------------------------------------------------------------- /src/esnext/concat.js: -------------------------------------------------------------------------------- 1 | let cu = require('auto-curry'); 2 | 3 | 4 | // concat :: [a] -> [a] -> [a] 5 | // Append two lists 6 | // If the first list is not finite, the result is the first list. 7 | function* concat(a, b) { 8 | for (let x of a) yield x; 9 | for (let x of b) yield x; 10 | } 11 | 12 | module.exports = cu(concat); 13 | -------------------------------------------------------------------------------- /src/esnext/splitAt.js: -------------------------------------------------------------------------------- 1 | let cu = require('auto-curry'); 2 | 3 | 4 | // splitAt :: Int -> [a] -> ([a], [a]) 5 | function splitAt(i, a) { 6 | let l = [], r = []; 7 | 8 | for (let x of a) { 9 | if (i) { 10 | l.push(x); 11 | i--; 12 | } 13 | else r.push(x); 14 | } 15 | return [l, r]; 16 | } 17 | 18 | 19 | module.exports = cu(splitAt); 20 | -------------------------------------------------------------------------------- /src/esnext/dropWhile.js: -------------------------------------------------------------------------------- 1 | let cu = require('auto-curry'); 2 | 3 | 4 | // dropWhile :: (a -> Bool) -> [a] -> [a] 5 | function* dropWhile(p, a) { 6 | let doneDropping = false; 7 | 8 | for (let x of a) { 9 | if (p(x) && !doneDropping) continue; 10 | else { 11 | doneDropping = true; 12 | yield x; 13 | } 14 | } 15 | } 16 | 17 | 18 | module.exports = cu(dropWhile); 19 | -------------------------------------------------------------------------------- /src/esnext/tail.js: -------------------------------------------------------------------------------- 1 | // tail :: [a] -> [a] 2 | // [a] should be non-empty 3 | function* tail(a) { 4 | let aIt = a[Symbol.iterator](); 5 | let aObj = aIt.next(); 6 | 7 | if (aObj.done) throw new Error('Cannot get tail of empty list'); 8 | while (true) { 9 | aObj = aIt.next(); 10 | if (aObj.done) break; 11 | else yield aObj.value; 12 | } 13 | } 14 | 15 | module.exports = tail; 16 | -------------------------------------------------------------------------------- /src/esnext/iterate.js: -------------------------------------------------------------------------------- 1 | let clone = require('clone'); 2 | let cu = require('auto-curry'); 3 | let isObject = require('./util').isObject; 4 | 5 | 6 | // iterate :: (a -> a) -> a -> [a] 7 | function* iterate(f, a) { 8 | while (true) { 9 | // See the comment in repeat 10 | if (!isObject(a)) yield a; 11 | else yield clone(a); 12 | a = f(a); 13 | } 14 | } 15 | 16 | module.exports = cu(iterate); 17 | -------------------------------------------------------------------------------- /src/es5/replicate.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var clone = require("clone"); 4 | var cu = require("auto-curry"); 5 | var isObject = require("./util").isObject; 6 | 7 | // replicate :: Int -> a -> [a] 8 | function replicate(n, a) { 9 | var res = []; 10 | 11 | // See the comment in repeat 12 | while (n--) { 13 | if (!isObject(a)) res.push(a);else res.push(clone(a)); 14 | } 15 | return res; 16 | } 17 | 18 | module.exports = cu(replicate); -------------------------------------------------------------------------------- /src/esnext/replicate.js: -------------------------------------------------------------------------------- 1 | let clone = require('clone'); 2 | let cu = require('auto-curry'); 3 | let isObject = require('./util').isObject; 4 | 5 | 6 | // replicate :: Int -> a -> [a] 7 | function replicate(n, a) { 8 | let res = []; 9 | 10 | // See the comment in repeat 11 | while (n--) { 12 | if (!isObject(a)) res.push(a); 13 | else res.push(clone(a)); 14 | } 15 | return res; 16 | } 17 | 18 | module.exports = cu(replicate); 19 | -------------------------------------------------------------------------------- /src/esnext/span.js: -------------------------------------------------------------------------------- 1 | let cu = require('auto-curry'); 2 | 3 | 4 | // span :: (a -> Bool) -> [a] -> ([a], [a]) 5 | function span(p, a) { 6 | let l = []; 7 | let r = []; 8 | let doneTaking = false; 9 | 10 | for (let x of a) { 11 | if (p(x) && !doneTaking) l.push(x); 12 | else { 13 | doneTaking = true; 14 | r.push(x); 15 | } 16 | } 17 | return [l, r]; 18 | } 19 | 20 | 21 | module.exports = cu(span); 22 | -------------------------------------------------------------------------------- /src/esnext/unzip.js: -------------------------------------------------------------------------------- 1 | // unzip :: [(a, b)] -> ([a], [b]) 2 | function unzip(a) { 3 | let res = [ 4 | [], 5 | [] 6 | ]; 7 | for (let x of a) { 8 | for (let y of x) { 9 | if (2 !== x.length) throw new SyntaxError('unzip expects a tuple to have exactly two elements'); 10 | let curr = res.shift(); 11 | 12 | curr.push(y); 13 | res.push(curr); 14 | } 15 | } 16 | return res; 17 | } 18 | 19 | module.exports = unzip; 20 | -------------------------------------------------------------------------------- /src/esnext/unzipN.js: -------------------------------------------------------------------------------- 1 | let replicate = require('./replicate'); 2 | 3 | // unzipN :: [(a, b, .... , n)] -> ([a], [b], ...., [n]) 4 | function unzipN(a) { 5 | let res; 6 | 7 | for (let x of a) { 8 | res = res || [...replicate(x.length, [])]; 9 | for (let y of x) { 10 | let curr = res.shift(); 11 | 12 | curr.push(y); 13 | res.push(curr); 14 | } 15 | } 16 | 17 | return res || []; 18 | } 19 | 20 | 21 | module.exports = unzipN; 22 | -------------------------------------------------------------------------------- /src/esnext/scanl.js: -------------------------------------------------------------------------------- 1 | let clone = require('clone'); 2 | let cu = require('auto-curry'); 3 | let isObject = require('./util').isObject; 4 | 5 | 6 | // scanl :: (b -> a -> b) -> b -> [a] -> [b] 7 | function* scanl(f, acc, xs) { 8 | acc = isObject(acc)? clone(acc) : acc; 9 | for (let x of xs) { 10 | yield acc; 11 | acc = isObject(acc)? clone(acc) : acc; 12 | acc = f(acc, x); 13 | } 14 | yield acc; 15 | } 16 | 17 | module.exports = cu(scanl); 18 | -------------------------------------------------------------------------------- /src/esnext/util.js: -------------------------------------------------------------------------------- 1 | // check if arg is an object 2 | // isObject :: a -> Bool 3 | exports.isObject = function isObject(arg) { 4 | return typeof arg === 'object' && arg !== null; 5 | }; 6 | 7 | // get iterator and object returned by iterator 8 | // getIteratorAndObj :: (Iterable a) => a -> Object 9 | exports.getIteratorAndObj = function getIteratorAndObj(iterable) { 10 | let xsIt = iterable[Symbol.iterator](); 11 | let itObj = xsIt.next(); 12 | 13 | return {xsIt, itObj}; 14 | }; 15 | -------------------------------------------------------------------------------- /src/esnext/unzip3.js: -------------------------------------------------------------------------------- 1 | // unzip3 :: [(a, b, c)] -> ([a], [b], [c]) 2 | function unzip3(a) { 3 | let res = [ 4 | [], 5 | [], 6 | [] 7 | ]; 8 | for (let x of a) { 9 | for (let y of x) { 10 | if (3 !== x.length) throw new SyntaxError('unzip3 expects a tuple to have exactly three elements'); 11 | let curr = res.shift(); 12 | 13 | curr.push(y); 14 | res.push(curr); 15 | } 16 | } 17 | return res; 18 | } 19 | 20 | 21 | module.exports = unzip3; 22 | -------------------------------------------------------------------------------- /src/esnext/init.js: -------------------------------------------------------------------------------- 1 | let getIteratorAndObj = require('./util').getIteratorAndObj; 2 | 3 | 4 | // init :: [a] -> [a] 5 | // [a] should be non-empty 6 | function* init(a) { 7 | let {xsIt, itObj} = getIteratorAndObj(a); 8 | let nextObj = xsIt.next(); 9 | 10 | if (itObj.done) throw new Error('Cannot get init of empty list'); 11 | while (!nextObj.done) { 12 | yield itObj.value; 13 | itObj = nextObj; 14 | nextObj = xsIt.next(); 15 | } 16 | } 17 | 18 | module.exports = init; 19 | -------------------------------------------------------------------------------- /src/esnext/zip.js: -------------------------------------------------------------------------------- 1 | let cu = require('auto-curry'); 2 | 3 | 4 | // zip :: [a] -> [b] -> [[a,b]] 5 | function* zip(a, b) { 6 | let aIterator = a[Symbol.iterator](); 7 | let bIterator = b[Symbol.iterator](); 8 | let aObj = aIterator.next(); 9 | let bObj = bIterator.next(); 10 | 11 | while (!aObj.done && !bObj.done) { 12 | yield [aObj.value, bObj.value]; 13 | aObj = aIterator.next(); 14 | bObj = bIterator.next(); 15 | } 16 | } 17 | 18 | 19 | module.exports = cu(zip); 20 | -------------------------------------------------------------------------------- /src/esnext/scanl1.js: -------------------------------------------------------------------------------- 1 | let clone = require('clone'); 2 | let cu = require('auto-curry'); 3 | let isObject = require('./util').isObject; 4 | 5 | 6 | // scanl1 :: (a -> a -> a) -> [a] -> [a] 7 | // scanl1 f [x1, x2, ...] == [x1, x1 `f` x2, ...] 8 | function* scanl1(f, xs) { 9 | let prev = null; 10 | 11 | for (let x of xs) { 12 | if (null !== prev) x = f(prev, x); 13 | yield x; 14 | x = isObject(x)? clone(x) : x; 15 | prev = x; 16 | } 17 | } 18 | 19 | module.exports = cu(scanl1); 20 | -------------------------------------------------------------------------------- /src/es5/util.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | // check if arg is an object 4 | // isObject :: a -> Bool 5 | exports.isObject = function isObject(arg) { 6 | return typeof arg === "object" && arg !== null; 7 | }; 8 | 9 | // get iterator and object returned by iterator 10 | // getIteratorAndObj :: (Iterable a) => a -> Object 11 | exports.getIteratorAndObj = function getIteratorAndObj(iterable) { 12 | var xsIt = iterable[Symbol.iterator](); 13 | var itObj = xsIt.next(); 14 | 15 | return { xsIt: xsIt, itObj: itObj }; 16 | }; -------------------------------------------------------------------------------- /src/esnext/take.js: -------------------------------------------------------------------------------- 1 | let cu = require('auto-curry'); 2 | 3 | 4 | // take :: Int -> [a] -> [a] 5 | function* take(n, a) { 6 | for (let x of a) { 7 | if (n > 1) { 8 | yield x; 9 | n--; 10 | } 11 | // this condition makes sure that we yield only 12 | // exactly n times and not n + 1 times which 13 | // would happen if we were using the old if (n--) code 14 | else if (n === 1) { 15 | yield x; 16 | break; 17 | } 18 | else break; 19 | } 20 | } 21 | 22 | module.exports = cu(take); 23 | -------------------------------------------------------------------------------- /src/esnext/zipWith.js: -------------------------------------------------------------------------------- 1 | let cu = require('auto-curry'); 2 | 3 | 4 | // zipWith :: (a -> b -> c) -> [a] -> [b] -> [c] 5 | function* zipWith(f, a, b) { 6 | let aIterator = a[Symbol.iterator](); 7 | let bIterator = b[Symbol.iterator](); 8 | let aObj = aIterator.next(); 9 | let bObj = bIterator.next(); 10 | 11 | while (!aObj.done && !bObj.done) { 12 | yield f(aObj.value, bObj.value); 13 | aObj = aIterator.next(); 14 | bObj = bIterator.next(); 15 | } 16 | } 17 | 18 | 19 | module.exports = cu(zipWith); 20 | -------------------------------------------------------------------------------- /test/repeat.test.js: -------------------------------------------------------------------------------- 1 | require('should'); 2 | 3 | var take = require('../src/esnext/take'); 4 | var repeat = require('../src/esnext/repeat'); 5 | 6 | 7 | describe('lazit#repeat', function() { 8 | it('normal operation check', function() { 9 | var res; 10 | 11 | res = [...take(4, repeat(1))]; 12 | res.should.eql([1,1,1,1]); 13 | }); 14 | it('empty list check', function() { 15 | var res, r; 16 | 17 | r = repeat([]); 18 | res = [...take(4, r)]; 19 | res.should.eql([[],[],[],[]]); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /src/es5/last.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var _toConsumableArray = function (arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } else { return Array.from(arr); } }; 4 | 5 | // last :: [a] -> a 6 | // [a] must be finite and non-empty 7 | function last(a) { 8 | if (a[Symbol.iterator]().next().done) throw new Error("Cannot get last of empty list"); 9 | if (!Array.isArray(a)) a = [].concat(_toConsumableArray(a)); 10 | return a[a.length - 1]; 11 | } 12 | 13 | module.exports = last; -------------------------------------------------------------------------------- /src/esnext/spanInv.js: -------------------------------------------------------------------------------- 1 | let cu = require('auto-curry'); 2 | 3 | 4 | // break :: (a -> Bool) -> [a] -> ([a], [a]) 5 | // calling it spanInv which stands for spanInverse 6 | // since break is a reserved word 7 | function spanInv(p, a) { 8 | let l = []; 9 | let r = []; 10 | let doneTaking = false; 11 | 12 | for (let x of a) { 13 | if (!p(x) && !doneTaking) l.push(x); 14 | else { 15 | doneTaking = true; 16 | r.push(x); 17 | } 18 | } 19 | return [l, r]; 20 | } 21 | 22 | 23 | module.exports = cu(spanInv); 24 | -------------------------------------------------------------------------------- /src/esnext/foldr.js: -------------------------------------------------------------------------------- 1 | let clone = require('clone'); 2 | let cu = require('auto-curry'); 3 | let isObject = require('./util').isObject; 4 | 5 | 6 | // foldr :: (a -> b -> b) -> b -> [a] -> b 7 | function foldr(f, acc, xs) { 8 | let xsIt = xs[Symbol.iterator](); 9 | 10 | acc = isObject(acc)? clone(acc) : acc; 11 | return _foldr(f, acc, xsIt); 12 | 13 | function _foldr(_f, _acc, _xsIt) { 14 | let _itObj = _xsIt.next(); 15 | 16 | if (_itObj.done) return _acc; 17 | return _f(_itObj.value, _foldr(_f, _acc, _xsIt)); 18 | } 19 | } 20 | 21 | module.exports = cu(foldr); 22 | -------------------------------------------------------------------------------- /src/es5/foldr.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var clone = require("clone"); 4 | var cu = require("auto-curry"); 5 | var isObject = require("./util").isObject; 6 | 7 | // foldr :: (a -> b -> b) -> b -> [a] -> b 8 | function foldr(f, acc, xs) { 9 | var xsIt = xs[Symbol.iterator](); 10 | 11 | acc = isObject(acc) ? clone(acc) : acc; 12 | return _foldr(f, acc, xsIt); 13 | 14 | function _foldr(_f, _acc, _xsIt) { 15 | var _itObj = _xsIt.next(); 16 | 17 | if (_itObj.done) { 18 | return _acc; 19 | }return _f(_itObj.value, _foldr(_f, _acc, _xsIt)); 20 | } 21 | } 22 | 23 | module.exports = cu(foldr); -------------------------------------------------------------------------------- /src/esnext/scanr.js: -------------------------------------------------------------------------------- 1 | let clone = require('clone'); 2 | let cu = require('auto-curry'); 3 | let isObject = require('./util').isObject; 4 | 5 | 6 | // scanr :: (a -> b -> b) -> b -> [a] -> [b] 7 | function scanr(f, acc, xs) { 8 | let xsIt = xs[Symbol.iterator](); 9 | 10 | return _scanr(f, acc, xsIt); 11 | 12 | function _scanr(_f, _b, _aIt) { 13 | let _aObj = _aIt.next(); 14 | let ys; 15 | 16 | if (_aObj.done) return [_b]; 17 | ys = _scanr(_f, _b, _aIt); 18 | ys.unshift(_f(_aObj.value, isObject(ys[0])? clone(ys[0]) : ys[0])); 19 | return ys; 20 | } 21 | } 22 | 23 | module.exports = cu(scanr); 24 | -------------------------------------------------------------------------------- /src/esnext/zipN.js: -------------------------------------------------------------------------------- 1 | /*eslint no-loop-func:0*/ 2 | 3 | // zipN :: [a] -> [b] .... -> [n] -> [[a..n]] 4 | // zips n lists together 5 | // zipN does NOT auto-curry since there's no way of 6 | // knowing it's arity till it's called i.e., it's 7 | // variadic and hence cannot be curried in javascript 8 | function* zipN(...args) { 9 | let iterators = args.map(v => v[Symbol.iterator]()); 10 | let itObjs = iterators.map(v => v.next()); 11 | 12 | while (itObjs.filter(v => !v.done).length === itObjs.length) { 13 | yield itObjs.map(v => v.value); 14 | itObjs = iterators.map(v => v.next()); 15 | } 16 | } 17 | 18 | 19 | module.exports = zipN; 20 | -------------------------------------------------------------------------------- /test/replicate.test.js: -------------------------------------------------------------------------------- 1 | require('should'); 2 | 3 | var replicate = require('../src/esnext/replicate'); 4 | 5 | 6 | describe('lazit#replicate', function() { 7 | it('normal operation check', function() { 8 | var res; 9 | 10 | res = replicate(4, 1); 11 | res.should.eql([1,1,1,1]); 12 | }); 13 | it('auto-curry check', function() { 14 | var res; 15 | var m = replicate(5); // auto-curry check 16 | 17 | res = m([]); 18 | res.should.eql([[],[],[],[],[]]); 19 | }); 20 | it('empty list check', function() { 21 | var res; 22 | 23 | res = replicate(4, []); 24 | res.should.eql([[],[],[],[]]); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /.jsbeautifyrc: -------------------------------------------------------------------------------- 1 | { 2 | "indent_size": 2, 3 | "indent_char": " ", 4 | "indent_level": 0, 5 | "indent_with_tabs": false, 6 | "preserve_newlines": true, 7 | "max_preserve_newlines": 4, 8 | "space_in_parens": false, 9 | "jslint_happy": false, 10 | "space_after_anon_function": false, 11 | "brace_style": "end-expand", 12 | "keep_array_indentation": false, 13 | "keep_function_indentation": false, 14 | "space_before_conditional": true, 15 | "break_chained_methods": false, 16 | "eval_code": false, 17 | "unescape_strings": false, 18 | "wrap_line_length": 0, 19 | "end_with_newline": true 20 | } 21 | 22 | -------------------------------------------------------------------------------- /src/esnext/zip3.js: -------------------------------------------------------------------------------- 1 | let cu = require('auto-curry'); 2 | 3 | 4 | // zip3 :: [a] -> [b] -> [c] -> [(a, b, c)] 5 | function* zip3(a, b, c) { 6 | let aIterator = a[Symbol.iterator](); 7 | let bIterator = b[Symbol.iterator](); 8 | let cIterator = c[Symbol.iterator](); 9 | let aObj = aIterator.next(); 10 | let bObj = bIterator.next(); 11 | let cObj = cIterator.next(); 12 | 13 | while (!aObj.done && !bObj.done && !cObj.done) { 14 | yield [aObj.value, bObj.value, cObj.value]; 15 | aObj = aIterator.next(); 16 | bObj = bIterator.next(); 17 | cObj = cIterator.next(); 18 | } 19 | } 20 | 21 | 22 | module.exports = cu(zip3); 23 | -------------------------------------------------------------------------------- /src/es5/scanr.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var clone = require("clone"); 4 | var cu = require("auto-curry"); 5 | var isObject = require("./util").isObject; 6 | 7 | // scanr :: (a -> b -> b) -> b -> [a] -> [b] 8 | function scanr(f, acc, xs) { 9 | var xsIt = xs[Symbol.iterator](); 10 | 11 | return _scanr(f, acc, xsIt); 12 | 13 | function _scanr(_f, _b, _aIt) { 14 | var _aObj = _aIt.next(); 15 | var ys = undefined; 16 | 17 | if (_aObj.done) { 18 | return [_b]; 19 | }ys = _scanr(_f, _b, _aIt); 20 | ys.unshift(_f(_aObj.value, isObject(ys[0]) ? clone(ys[0]) : ys[0])); 21 | return ys; 22 | } 23 | } 24 | 25 | module.exports = cu(scanr); -------------------------------------------------------------------------------- /src/esnext/repeat.js: -------------------------------------------------------------------------------- 1 | let clone = require('clone'); 2 | let isObject = require('./util').isObject; 3 | 4 | 5 | // repeat :: a -> [a] 6 | function* repeat(a) { 7 | // cloning since objects are basically pointers in js. 8 | // If I just `yield a` then all the elements in the resulting 9 | // list will contain reference to the same object and all hell 10 | // will break loose, it'll rain cows and horses, ketchup will 11 | // replace water and all the liquour in the world will disappear. 12 | // Saving your life here, man. 13 | while (true) { 14 | if (!isObject(a)) yield a; 15 | else yield clone(a); 16 | } 17 | } 18 | 19 | module.exports = repeat; 20 | -------------------------------------------------------------------------------- /src/esnext/zipWithN.js: -------------------------------------------------------------------------------- 1 | /*eslint no-loop-func:0*/ 2 | 3 | // zipWithN :: (a -> b -> .... -> n -> x) -> [a] -> [b] -> .... -> [n] -> [x] 4 | // applies a function to a each element in a zip of n lists and returns new list 5 | // zipWithN does NOT auto-curry since it's variadic 6 | function* zipWithN(f, ...args) { 7 | let iterators = args.map(v => v[Symbol.iterator]()); 8 | let itObjs = iterators.map(v => v.next()); 9 | 10 | while (itObjs.filter(v => !v.done).length === itObjs.length) { 11 | let temp = itObjs.map(v => v.value); 12 | 13 | yield f.apply(null, temp); 14 | itObjs = iterators.map(v => v.next()); 15 | } 16 | } 17 | 18 | module.exports = zipWithN; 19 | -------------------------------------------------------------------------------- /src/esnext/zipWith3.js: -------------------------------------------------------------------------------- 1 | let cu = require('auto-curry'); 2 | 3 | 4 | // zipWith3 :: (a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d] 5 | function* zipWith3(f, a, b, c) { 6 | let aIterator = a[Symbol.iterator](); 7 | let bIterator = b[Symbol.iterator](); 8 | let cIterator = c[Symbol.iterator](); 9 | let aObj = aIterator.next(); 10 | let bObj = bIterator.next(); 11 | let cObj = cIterator.next(); 12 | 13 | while (!aObj.done && !bObj.done && !cObj.done) { 14 | yield f(aObj.value, bObj.value, cObj.value); 15 | aObj = aIterator.next(); 16 | bObj = bIterator.next(); 17 | cObj = cIterator.next(); 18 | } 19 | } 20 | 21 | 22 | module.exports = cu(zipWith3); 23 | -------------------------------------------------------------------------------- /src/esnext/cycle.js: -------------------------------------------------------------------------------- 1 | let clone = require('clone'); 2 | let isObject = require('./util').isObject; 3 | let isGenFn = require('is-generator').fn; 4 | 5 | 6 | // cycle :: [a] -> [a] 7 | function* cycle(a) { 8 | let isGenFnFlag = isGenFn(a); 9 | let tempIt = isGenFnFlag ? a()[Symbol.iterator]() : a[Symbol.iterator](); 10 | 11 | if (tempIt.next().done) throw new Error('Cannot cycle empty list/iterable'); 12 | 13 | function* yieldIt(x) { 14 | if (!isObject(x)) yield x; 15 | else yield clone(x); 16 | } 17 | 18 | while (true) { 19 | // See the comment in repeat 20 | if (!isGenFnFlag) for (let x of a) yield* yieldIt(x); 21 | else for (let x of a()) yield* yieldIt(x); 22 | } 23 | } 24 | 25 | module.exports = cycle; 26 | -------------------------------------------------------------------------------- /test/iterate.test.js: -------------------------------------------------------------------------------- 1 | require('should'); 2 | 3 | var take = require('../src/esnext/take'); 4 | var iterate = require('../src/esnext/iterate'); 5 | 6 | 7 | describe('lazit#iterate', function() { 8 | it('normal operation check', function() { 9 | var res; 10 | 11 | res = [...take(4, iterate(v => v+1, 1))]; 12 | res.should.eql([1,2,3,4]); 13 | }); 14 | it('auto-curry check', function() { 15 | var res; 16 | var m = iterate(a => a); // auto-curry check 17 | 18 | res = [...take(4, m(1))]; 19 | res.should.eql([1,1,1,1]); 20 | }); 21 | it('empty list check', function() { 22 | var res, i; 23 | 24 | i = iterate(v => v, []); 25 | res = [...take(4, i)]; 26 | res.should.eql([[],[],[],[]]); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /src/esnext/foldr1.js: -------------------------------------------------------------------------------- 1 | let clone = require('clone'); 2 | let cu = require('auto-curry'); 3 | let isObject = require('./util').isObject; 4 | let getIteratorAndObj = require('./util').getIteratorAndObj; 5 | 6 | 7 | // foldr1 :: (a -> a -> a) -> [a] -> a 8 | function foldr1(f, xs) { 9 | let {xsIt, itObj} = getIteratorAndObj(xs); 10 | 11 | if (itObj.done) throw new Error('Cannot apply foldr1 to an empty list'); 12 | 13 | return _foldr1(f, itObj.value, xsIt); 14 | 15 | function _foldr1(_f, _acc, _xsIt) { 16 | let _itObj = _xsIt.next(); 17 | 18 | if (_itObj.done) return isObject(_acc)? clone(_acc) : _acc; 19 | return _f(_acc, _foldr1(_f, _itObj.value, _xsIt)); 20 | } 21 | } 22 | 23 | module.exports = cu(foldr1); 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.gitignore.io 2 | 3 | ### Node ### 4 | # Logs 5 | logs 6 | *.log 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | 13 | # Directory for instrumented libs generated by jscoverage/JSCover 14 | lib-cov 15 | 16 | # Coverage directory used by tools like istanbul 17 | coverage 18 | 19 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 20 | .grunt 21 | 22 | # node-waf configuration 23 | .lock-wscript 24 | 25 | # Compiled binary addons (http://nodejs.org/api/addons.html) 26 | build/Release 27 | 28 | # Dependency directory 29 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git- 30 | node_modules 31 | 32 | # Tern stuff 33 | .tern-port 34 | 35 | # TAGS 36 | TAGS 37 | -------------------------------------------------------------------------------- /src/esnext/scanr1.js: -------------------------------------------------------------------------------- 1 | //var cu = require('auto-curry'); 2 | 3 | 4 | // fix this implementation ffs 5 | // scanr1 :: (a -> a -> a) -> [a] -> [a] 6 | // function scanr1(f, xs){ 7 | // var itObj = xs[Symbol.iterator]().next(); 8 | // if (itObj.done) return []; 9 | // else return _scanr1(f, itObj.value, xs[Symbol.iterator]()); 10 | 11 | // function _scanr1(_f, _b, _aIt) { 12 | // let _aObj = _aIt.next(); 13 | // if (_aObj.done) return _b; 14 | // let ys = _scanr1(_f, _b, _aIt); 15 | // if (Array.isArray(ys)) ys.unshift(_f(_aObj.value, ys[0])); 16 | // else { 17 | // let temp = []; 18 | // temp.push(_f(_aObj.value, ys)); 19 | // ys = temp; 20 | // } 21 | // return ys; 22 | // } 23 | // } 24 | 25 | //module.exports = cu(scanr1); 26 | -------------------------------------------------------------------------------- /src/es5/scanr1.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | //var cu = require('auto-curry'); 4 | 5 | // fix this implementation ffs 6 | // scanr1 :: (a -> a -> a) -> [a] -> [a] 7 | // function scanr1(f, xs){ 8 | // var itObj = xs[Symbol.iterator]().next(); 9 | // if (itObj.done) return []; 10 | // else return _scanr1(f, itObj.value, xs[Symbol.iterator]()); 11 | 12 | // function _scanr1(_f, _b, _aIt) { 13 | // let _aObj = _aIt.next(); 14 | // if (_aObj.done) return _b; 15 | // let ys = _scanr1(_f, _b, _aIt); 16 | // if (Array.isArray(ys)) ys.unshift(_f(_aObj.value, ys[0])); 17 | // else { 18 | // let temp = []; 19 | // temp.push(_f(_aObj.value, ys)); 20 | // ys = temp; 21 | // } 22 | // return ys; 23 | // } 24 | // } 25 | 26 | //module.exports = cu(scanr1); -------------------------------------------------------------------------------- /src/esnext/foldl.js: -------------------------------------------------------------------------------- 1 | let clone = require('clone'); 2 | let cu = require('auto-curry'); 3 | let isObject = require('./util').isObject; 4 | let getIteratorAndObj = require('./util').getIteratorAndObj; 5 | 6 | 7 | // reducing lists 8 | // foldl :: (b -> a -> b) -> b -> [a] -> b 9 | // input list must be finite 10 | function foldl(f, acc, xs) { 11 | let {xsIt, itObj} = getIteratorAndObj(xs); 12 | 13 | // clone to prevent input mutation 14 | if (isObject(acc)) acc = clone(acc); 15 | 16 | // unrolling recursive foldl definition 17 | // into a simple loop 18 | // like a tail call optimizer would have done 19 | while (!itObj.done) { 20 | acc = f(acc, itObj.value); 21 | itObj = xsIt.next(); 22 | } 23 | return acc; 24 | } 25 | 26 | module.exports = cu(foldl); 27 | -------------------------------------------------------------------------------- /test/head.test.js: -------------------------------------------------------------------------------- 1 | require('should'); 2 | 3 | var head = require('../src/esnext/head'); 4 | var iterate = require('../src/esnext/iterate'); 5 | 6 | describe('lazit#head', function() { 7 | it('normal operation check', function() { 8 | var res; 9 | 10 | res = head([1,2,3,4]); 11 | res.should.eql(1); 12 | 13 | res = head(iterate(v => v+1, 10)); 14 | res.should.eql(10); 15 | }); 16 | it('custom iterator check', function() { 17 | var res; 18 | 19 | function* customIterator(){ 20 | yield 'a'; 21 | yield 1; 22 | } 23 | 24 | res = head(customIterator()); 25 | res.should.eql('a'); 26 | }); 27 | it('empty list check', function() { 28 | var res; 29 | 30 | res = head.bind(null, []).should.throw('Cannot get head of empty list'); 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /src/esnext/foldl1.js: -------------------------------------------------------------------------------- 1 | let clone = require('clone'); 2 | let cu = require('auto-curry'); 3 | let isObject = require('./util').isObject; 4 | let getIteratorAndObj = require('./util').getIteratorAndObj; 5 | 6 | 7 | // foldl1 :: (a -> a -> a) -> [a] -> a 8 | function foldl1(f, xs) { 9 | let {xsIt, itObj} = getIteratorAndObj(xs); 10 | // because pass by reference 11 | let acc = isObject(itObj.value)? clone(itObj.value) : itObj.value; 12 | let nextVal; 13 | 14 | if (itObj.done) throw new Error('Cannot apply foldl1 to an empty list'); 15 | 16 | itObj = xsIt.next(); 17 | nextVal = itObj.value; 18 | 19 | while (!itObj.done) { 20 | acc = f(acc, nextVal); 21 | itObj = xsIt.next(); 22 | nextVal = itObj.value; 23 | } 24 | return acc; 25 | } 26 | 27 | module.exports = cu(foldl1); 28 | -------------------------------------------------------------------------------- /src/es5/foldr1.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var clone = require("clone"); 4 | var cu = require("auto-curry"); 5 | var isObject = require("./util").isObject; 6 | var getIteratorAndObj = require("./util").getIteratorAndObj; 7 | 8 | // foldr1 :: (a -> a -> a) -> [a] -> a 9 | function foldr1(f, xs) { 10 | var _getIteratorAndObj = getIteratorAndObj(xs); 11 | 12 | var xsIt = _getIteratorAndObj.xsIt; 13 | var itObj = _getIteratorAndObj.itObj; 14 | 15 | if (itObj.done) throw new Error("Cannot apply foldr1 to an empty list"); 16 | 17 | return _foldr1(f, itObj.value, xsIt); 18 | 19 | function _foldr1(_f, _acc, _xsIt) { 20 | var _itObj = _xsIt.next(); 21 | 22 | if (_itObj.done) { 23 | return isObject(_acc) ? clone(_acc) : _acc; 24 | }return _f(_acc, _foldr1(_f, _itObj.value, _xsIt)); 25 | } 26 | } 27 | 28 | module.exports = cu(foldr1); -------------------------------------------------------------------------------- /test/last.test.js: -------------------------------------------------------------------------------- 1 | require('should'); 2 | 3 | var last = require('../src/esnext/last'); 4 | var take = require('../src/esnext/take'); 5 | var iterate = require('../src/esnext/iterate'); 6 | 7 | describe('lazit#last', function() { 8 | it('normal operation check', function() { 9 | var res; 10 | 11 | res = last([1,2,3,4]); 12 | res.should.eql(4); 13 | 14 | res = last(take(4, iterate(v => v + 1, 0))); 15 | res.should.eql(3); 16 | }); 17 | it('custom iterator check', function() { 18 | var res; 19 | 20 | function* customIterator(){ 21 | yield 'a'; 22 | yield 1; 23 | yield 'b'; 24 | yield 2; 25 | } 26 | 27 | res = last(customIterator()); 28 | res.should.eql(2); 29 | }); 30 | it('empty list check', function() { 31 | last.bind(null, []).should.throw('Cannot get last of empty list'); 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /src/es5/foldl.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var clone = require("clone"); 4 | var cu = require("auto-curry"); 5 | var isObject = require("./util").isObject; 6 | var getIteratorAndObj = require("./util").getIteratorAndObj; 7 | 8 | // reducing lists 9 | // foldl :: (b -> a -> b) -> b -> [a] -> b 10 | // input list must be finite 11 | function foldl(f, acc, xs) { 12 | var _getIteratorAndObj = getIteratorAndObj(xs); 13 | 14 | var xsIt = _getIteratorAndObj.xsIt; 15 | var itObj = _getIteratorAndObj.itObj; 16 | 17 | // clone to prevent input mutation 18 | if (isObject(acc)) acc = clone(acc); 19 | 20 | // unrolling recursive foldl definition 21 | // into a simple loop 22 | // like a tail call optimizer would have done 23 | while (!itObj.done) { 24 | acc = f(acc, itObj.value); 25 | itObj = xsIt.next(); 26 | } 27 | return acc; 28 | } 29 | 30 | module.exports = cu(foldl); -------------------------------------------------------------------------------- /test/unzip.test.js: -------------------------------------------------------------------------------- 1 | require('should'); 2 | 3 | var unzip = require('../src/esnext/unzip'); 4 | 5 | 6 | describe('lazit#unzip', function() { 7 | it('normal operation check', function() { 8 | var res; 9 | 10 | res = unzip([[1,5], [2,6]]); 11 | res.should.eql([[1,2], [5,6]]); 12 | 13 | res = unzip([[0,3], [1,5], [2,17], [3,257]]); 14 | res.should.eql([[0,1,2,3], [3,5,17,257]]); 15 | 16 | res = unzip.bind(null, [[1,5,10], [2,6,20]]); 17 | res.should.throw(); 18 | }); 19 | it('custom iterator check', function() { 20 | var res; 21 | 22 | function* customIterator(){ 23 | yield ['a', 'c']; 24 | yield [1, 3]; 25 | } 26 | 27 | res = unzip(customIterator()); 28 | res.should.eql([['a', 1], ['c', 3]]); 29 | }); 30 | 31 | it('empty list check', function() { 32 | var res; 33 | 34 | res = unzip([]); 35 | res.should.eql([[],[]]); 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /src/es5/foldl1.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var clone = require("clone"); 4 | var cu = require("auto-curry"); 5 | var isObject = require("./util").isObject; 6 | var getIteratorAndObj = require("./util").getIteratorAndObj; 7 | 8 | // foldl1 :: (a -> a -> a) -> [a] -> a 9 | function foldl1(f, xs) { 10 | var _getIteratorAndObj = getIteratorAndObj(xs); 11 | 12 | var xsIt = _getIteratorAndObj.xsIt; 13 | var itObj = _getIteratorAndObj.itObj; 14 | 15 | // because pass by reference 16 | var acc = isObject(itObj.value) ? clone(itObj.value) : itObj.value; 17 | var nextVal = undefined; 18 | 19 | if (itObj.done) throw new Error("Cannot apply foldl1 to an empty list"); 20 | 21 | itObj = xsIt.next(); 22 | nextVal = itObj.value; 23 | 24 | while (!itObj.done) { 25 | acc = f(acc, nextVal); 26 | itObj = xsIt.next(); 27 | nextVal = itObj.value; 28 | } 29 | return acc; 30 | } 31 | 32 | module.exports = cu(foldl1); -------------------------------------------------------------------------------- /src/es5/reverse.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | // reverse :: [a] -> [a] 4 | // [a] should be finite 5 | function reverse(a) { 6 | var res = []; 7 | 8 | var _iteratorNormalCompletion = true; 9 | var _didIteratorError = false; 10 | var _iteratorError = undefined; 11 | 12 | try { 13 | for (var _iterator = a[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { 14 | var x = _step.value; 15 | res.unshift(x); 16 | } 17 | } catch (err) { 18 | _didIteratorError = true; 19 | _iteratorError = err; 20 | } finally { 21 | try { 22 | if (!_iteratorNormalCompletion && _iterator["return"]) { 23 | _iterator["return"](); 24 | } 25 | } finally { 26 | if (_didIteratorError) { 27 | throw _iteratorError; 28 | } 29 | } 30 | } 31 | 32 | return res; 33 | } 34 | 35 | module.exports = reverse; -------------------------------------------------------------------------------- /test/unzip3.test.js: -------------------------------------------------------------------------------- 1 | require('should'); 2 | 3 | var unzip3 = require('../src/esnext/unzip3'); 4 | 5 | 6 | describe('lazit#unzip3', function() { 7 | it('normal operation check', function() { 8 | var res; 9 | 10 | res = unzip3([[1,5,4], [2,6,5]]); 11 | res.should.eql([[1,2], [5,6], [4,5]]); 12 | 13 | res = unzip3([[0,3,10], [1,5,30], [2,17,50], [3,257,70]]); 14 | res.should.eql([[0,1,2,3], [3,5,17,257], [10,30,50,70]]); 15 | 16 | res = unzip3.bind(null, [[1,5,4,0], [2,6,5,1]]); 17 | res.should.throw(); 18 | }); 19 | it('custom iterator check', function() { 20 | var res; 21 | 22 | function* customIterator(){ 23 | yield ['a', 'c', 'd']; 24 | yield [1, 3, 5]; 25 | } 26 | 27 | res = unzip3(customIterator()); 28 | res.should.eql([['a', 1], ['c', 3], ['d', 5]]); 29 | }); 30 | it('empty list check', function() { 31 | var res; 32 | 33 | res = unzip3([]); 34 | res.should.eql([[],[],[]]); 35 | }); 36 | }); 37 | -------------------------------------------------------------------------------- /test/map.test.js: -------------------------------------------------------------------------------- 1 | require('should'); 2 | 3 | var map = require('../src/esnext/map'); 4 | var take = require('../src/esnext/take'); 5 | var iterate = require('../src/esnext/iterate'); 6 | 7 | describe('lazit#map', function() { 8 | it('normal operation check', function() { 9 | var res; 10 | 11 | res = [...map(v => ++v, [1,2,3,4])]; 12 | res.should.eql([2,3,4,5]); 13 | }); 14 | it('auto-curry check', function() { 15 | var res, m; 16 | 17 | m = map(v => v*v); // auto-curry check 18 | 19 | res = [...take(4, m(iterate(v => v+1, 1)))]; 20 | res.should.eql([1,4,9,16]); 21 | }); 22 | it('custom iterator check', function() { 23 | var res; 24 | 25 | function* customIterator(){ 26 | yield 1; 27 | yield 'a'; 28 | } 29 | 30 | res = [...map(v => v+' dude', customIterator())]; 31 | res.should.eql(['1 dude', 'a dude']); 32 | }); 33 | it('empty list check', function() { 34 | var res; 35 | 36 | res = [...map(v => ++v, [])]; 37 | res.should.eql([]); 38 | }); 39 | }); 40 | -------------------------------------------------------------------------------- /src/es5/splitAt.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var cu = require("auto-curry"); 4 | 5 | // splitAt :: Int -> [a] -> ([a], [a]) 6 | function splitAt(i, a) { 7 | var l = [], 8 | r = []; 9 | 10 | var _iteratorNormalCompletion = true; 11 | var _didIteratorError = false; 12 | var _iteratorError = undefined; 13 | 14 | try { 15 | for (var _iterator = a[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { 16 | var x = _step.value; 17 | 18 | if (i) { 19 | l.push(x); 20 | i--; 21 | } else r.push(x); 22 | } 23 | } catch (err) { 24 | _didIteratorError = true; 25 | _iteratorError = err; 26 | } finally { 27 | try { 28 | if (!_iteratorNormalCompletion && _iterator["return"]) { 29 | _iterator["return"](); 30 | } 31 | } finally { 32 | if (_didIteratorError) { 33 | throw _iteratorError; 34 | } 35 | } 36 | } 37 | 38 | return [l, r]; 39 | } 40 | 41 | module.exports = cu(splitAt); -------------------------------------------------------------------------------- /src/es5/zip.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var zip = regeneratorRuntime.mark( 4 | 5 | // zip :: [a] -> [b] -> [[a,b]] 6 | function zip(a, b) { 7 | var aIterator, bIterator, aObj, bObj; 8 | return regeneratorRuntime.wrap(function zip$(context$1$0) { 9 | while (1) switch (context$1$0.prev = context$1$0.next) { 10 | case 0: 11 | aIterator = a[Symbol.iterator](); 12 | bIterator = b[Symbol.iterator](); 13 | aObj = aIterator.next(); 14 | bObj = bIterator.next(); 15 | 16 | case 4: 17 | if (!(!aObj.done && !bObj.done)) { 18 | context$1$0.next = 11; 19 | break; 20 | } 21 | 22 | context$1$0.next = 7; 23 | return [aObj.value, bObj.value]; 24 | 25 | case 7: 26 | aObj = aIterator.next(); 27 | bObj = bIterator.next(); 28 | context$1$0.next = 4; 29 | break; 30 | 31 | case 11: 32 | case "end": 33 | return context$1$0.stop(); 34 | } 35 | }, zip, this); 36 | }); 37 | var cu = require("auto-curry"); 38 | 39 | module.exports = cu(zip); -------------------------------------------------------------------------------- /test/unzipN.test.js: -------------------------------------------------------------------------------- 1 | require('should'); 2 | 3 | var unzipN = require('../src/esnext/unzipN'); 4 | 5 | 6 | describe('lazit#unzipN', function() { 7 | it('normal operation check', function() { 8 | var res; 9 | 10 | res = unzipN([[1,5], [2,6], [0,1], [2,4]]); 11 | res.should.eql([[1,2,0,2], [5,6,1,4]]); 12 | 13 | res = unzipN([[0,3,10], [1,5,20], [2,17,30], [3,257,40]]); 14 | res.should.eql([[0,1,2,3], [3,5,17,257], [10,20,30,40]]); 15 | }); 16 | it('custom iterator check', function() { 17 | var res; 18 | 19 | function* customIterator(){ 20 | yield ['a', 'c', 'm', 't']; 21 | yield [1, 3, 5, 200]; 22 | yield [0,0,0,1]; 23 | yield ['d','u','d','e']; 24 | } 25 | 26 | res = unzipN(customIterator()); 27 | res.should.eql([['a', 1, 0, 'd'], ['c', 3, 0, 'u'], ['m', 5, 0, 'd'], ['t', 200, 1, 'e']]); 28 | }); 29 | 30 | it('empty list check', function() { 31 | var res; 32 | 33 | res = unzipN([]); 34 | res.should.eql([]); 35 | res = unzipN([[],[]]); 36 | res.should.eql([]); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /src/es5/span.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var cu = require("auto-curry"); 4 | 5 | // span :: (a -> Bool) -> [a] -> ([a], [a]) 6 | function span(p, a) { 7 | var l = []; 8 | var r = []; 9 | var doneTaking = false; 10 | 11 | var _iteratorNormalCompletion = true; 12 | var _didIteratorError = false; 13 | var _iteratorError = undefined; 14 | 15 | try { 16 | for (var _iterator = a[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { 17 | var x = _step.value; 18 | 19 | if (p(x) && !doneTaking) l.push(x);else { 20 | doneTaking = true; 21 | r.push(x); 22 | } 23 | } 24 | } catch (err) { 25 | _didIteratorError = true; 26 | _iteratorError = err; 27 | } finally { 28 | try { 29 | if (!_iteratorNormalCompletion && _iterator["return"]) { 30 | _iterator["return"](); 31 | } 32 | } finally { 33 | if (_didIteratorError) { 34 | throw _iteratorError; 35 | } 36 | } 37 | } 38 | 39 | return [l, r]; 40 | } 41 | 42 | module.exports = cu(span); -------------------------------------------------------------------------------- /src/es5/zipWith.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var zipWith = regeneratorRuntime.mark( 4 | 5 | // zipWith :: (a -> b -> c) -> [a] -> [b] -> [c] 6 | function zipWith(f, a, b) { 7 | var aIterator, bIterator, aObj, bObj; 8 | return regeneratorRuntime.wrap(function zipWith$(context$1$0) { 9 | while (1) switch (context$1$0.prev = context$1$0.next) { 10 | case 0: 11 | aIterator = a[Symbol.iterator](); 12 | bIterator = b[Symbol.iterator](); 13 | aObj = aIterator.next(); 14 | bObj = bIterator.next(); 15 | 16 | case 4: 17 | if (!(!aObj.done && !bObj.done)) { 18 | context$1$0.next = 11; 19 | break; 20 | } 21 | 22 | context$1$0.next = 7; 23 | return f(aObj.value, bObj.value); 24 | 25 | case 7: 26 | aObj = aIterator.next(); 27 | bObj = bIterator.next(); 28 | context$1$0.next = 4; 29 | break; 30 | 31 | case 11: 32 | case "end": 33 | return context$1$0.stop(); 34 | } 35 | }, zipWith, this); 36 | }); 37 | var cu = require("auto-curry"); 38 | 39 | module.exports = cu(zipWith); -------------------------------------------------------------------------------- /test/tail.test.js: -------------------------------------------------------------------------------- 1 | require('should'); 2 | 3 | var map = require('../src/esnext/map'); 4 | var tail = require('../src/esnext/tail'); 5 | var take = require('../src/esnext/take'); 6 | var iterate = require('../src/esnext/iterate'); 7 | 8 | 9 | describe('lazit#tail', function() { 10 | it('normal operation check', function() { 11 | var res; 12 | 13 | res = [...tail([1,2,3,4])]; 14 | res.should.eql([2,3,4]); 15 | 16 | res = [...tail(map(v => ++v, take(5, iterate(v => v*v, 2))))]; 17 | res.should.eql([5,17,257,65537]); 18 | }); 19 | it('custom iterator check', function() { 20 | var res; 21 | 22 | function* customIterator(){ 23 | yield 'a'; 24 | yield 1; 25 | yield 'b'; 26 | yield 2; 27 | } 28 | 29 | res = [...tail(customIterator())]; 30 | res.should.eql([1, 'b', 2]); 31 | }); 32 | it('empty list check', function(done) { 33 | try { 34 | // throw mofo 35 | for (let x of tail([])) console.log(x); 36 | } 37 | catch(e){ 38 | e.message.should.eql('Cannot get tail of empty list'); 39 | done(); 40 | } 41 | }); 42 | }); 43 | -------------------------------------------------------------------------------- /test/reverse.test.js: -------------------------------------------------------------------------------- 1 | require('should'); 2 | 3 | var map = require('../src/esnext/map'); 4 | var take = require('../src/esnext/take'); 5 | var iterate = require('../src/esnext/iterate'); 6 | var reverse = require('../src/esnext/reverse'); 7 | 8 | describe('lazit#reverse', function() { 9 | it('normal operation check', function() { 10 | var res; 11 | 12 | res = reverse([1,2,3,4]); 13 | res.should.eql([4,3,2,1]); 14 | 15 | res = reverse(map(v => ++v, take(5, iterate(v => v*v, 2)))); 16 | res.should.eql([65537, 257, 17, 5, 3]); 17 | }); 18 | it('custom iterator check', function() { 19 | var res; 20 | 21 | function* customIterator(){ 22 | yield 'a'; 23 | yield 1; 24 | yield 'b'; 25 | yield 2; 26 | } 27 | 28 | function* delegator(){ 29 | yield* customIterator(); 30 | yield 'c'; 31 | yield 3; 32 | return 4; 33 | } 34 | 35 | res = reverse(delegator()); 36 | res.should.eql([3,'c',2,'b',1,'a']); 37 | }); 38 | 39 | it('empty list check', function() { 40 | var res; 41 | 42 | res = reverse([]); 43 | res.should.eql([]); 44 | }); 45 | }); 46 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Mudit Ameta 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /src/es5/iterate.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var iterate = regeneratorRuntime.mark( 4 | 5 | // iterate :: (a -> a) -> a -> [a] 6 | function iterate(f, a) { 7 | return regeneratorRuntime.wrap(function iterate$(context$1$0) { 8 | while (1) switch (context$1$0.prev = context$1$0.next) { 9 | case 0: 10 | if (!true) { 11 | context$1$0.next = 11; 12 | break; 13 | } 14 | 15 | if (isObject(a)) { 16 | context$1$0.next = 6; 17 | break; 18 | } 19 | 20 | context$1$0.next = 4; 21 | return a; 22 | 23 | case 4: 24 | context$1$0.next = 8; 25 | break; 26 | 27 | case 6: 28 | context$1$0.next = 8; 29 | return clone(a); 30 | 31 | case 8: 32 | a = f(a); 33 | context$1$0.next = 0; 34 | break; 35 | 36 | case 11: 37 | case "end": 38 | return context$1$0.stop(); 39 | } 40 | }, iterate, this); 41 | }); 42 | var clone = require("clone"); 43 | var cu = require("auto-curry"); 44 | var isObject = require("./util").isObject; 45 | 46 | module.exports = cu(iterate); 47 | 48 | // See the comment in repeat -------------------------------------------------------------------------------- /test/filter.test.js: -------------------------------------------------------------------------------- 1 | require('should'); 2 | 3 | var filter = require('../src/esnext/filter'); 4 | var take = require('../src/esnext/take'); 5 | var iterate = require('../src/esnext/iterate'); 6 | 7 | describe('lazit#filter', function() { 8 | it('normal operation check', function() { 9 | var res; 10 | 11 | res = [...filter(v => v > 2, [1,2,3,4])]; 12 | res.should.eql([3,4]); 13 | 14 | res = [...filter(v => v > 200, [1,2,3,4])]; 15 | res.should.eql([]); 16 | }); 17 | it('auto-curry check', function() { 18 | var res, m; 19 | 20 | m = filter(v => v < 9); // auto-curry check 21 | 22 | res = [...take(5, m(iterate(v => v+1, 1)))]; 23 | res.should.eql([1,2,3,4,5]); 24 | }); 25 | it('custom iterator check', function() { 26 | var res; 27 | 28 | function* customIterator(){ 29 | yield 'a'; 30 | yield 1; 31 | yield 'b'; 32 | yield 2; 33 | } 34 | 35 | res = [...filter(v => 'string' === typeof v, customIterator())]; 36 | res.should.eql(['a', 'b']); 37 | }); 38 | it('empty list check', function() { 39 | var res; 40 | 41 | res = [...filter(v => v > 10, [])]; 42 | res.should.eql([]); 43 | }); 44 | }); 45 | -------------------------------------------------------------------------------- /src/es5/spanInv.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var cu = require("auto-curry"); 4 | 5 | // break :: (a -> Bool) -> [a] -> ([a], [a]) 6 | // calling it spanInv which stands for spanInverse 7 | // since break is a reserved word 8 | function spanInv(p, a) { 9 | var l = []; 10 | var r = []; 11 | var doneTaking = false; 12 | 13 | var _iteratorNormalCompletion = true; 14 | var _didIteratorError = false; 15 | var _iteratorError = undefined; 16 | 17 | try { 18 | for (var _iterator = a[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { 19 | var x = _step.value; 20 | 21 | if (!p(x) && !doneTaking) l.push(x);else { 22 | doneTaking = true; 23 | r.push(x); 24 | } 25 | } 26 | } catch (err) { 27 | _didIteratorError = true; 28 | _iteratorError = err; 29 | } finally { 30 | try { 31 | if (!_iteratorNormalCompletion && _iterator["return"]) { 32 | _iterator["return"](); 33 | } 34 | } finally { 35 | if (_didIteratorError) { 36 | throw _iteratorError; 37 | } 38 | } 39 | } 40 | 41 | return [l, r]; 42 | } 43 | 44 | module.exports = cu(spanInv); -------------------------------------------------------------------------------- /src/es5/tail.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var tail = regeneratorRuntime.mark( // tail :: [a] -> [a] 4 | // [a] should be non-empty 5 | function tail(a) { 6 | var aIt, aObj; 7 | return regeneratorRuntime.wrap(function tail$(context$1$0) { 8 | while (1) switch (context$1$0.prev = context$1$0.next) { 9 | case 0: 10 | aIt = a[Symbol.iterator](); 11 | aObj = aIt.next(); 12 | 13 | if (!aObj.done) { 14 | context$1$0.next = 4; 15 | break; 16 | } 17 | 18 | throw new Error("Cannot get tail of empty list"); 19 | 20 | case 4: 21 | if (!true) { 22 | context$1$0.next = 14; 23 | break; 24 | } 25 | 26 | aObj = aIt.next(); 27 | 28 | if (!aObj.done) { 29 | context$1$0.next = 10; 30 | break; 31 | } 32 | 33 | return context$1$0.abrupt("break", 14); 34 | 35 | case 10: 36 | context$1$0.next = 12; 37 | return aObj.value; 38 | 39 | case 12: 40 | context$1$0.next = 4; 41 | break; 42 | 43 | case 14: 44 | case "end": 45 | return context$1$0.stop(); 46 | } 47 | }, tail, this); 48 | }); 49 | 50 | module.exports = tail; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lazit", 3 | "version": "1.0.0-rc.3", 4 | "description": "Lazy, composable operations on iterators/generators for ES6 and beyond.", 5 | "main": "build/lazit.js", 6 | "directories": { 7 | "test": "test" 8 | }, 9 | "scripts": { 10 | "test": "make test" 11 | }, 12 | "keywords": [ 13 | "list", 14 | "comprehensions", 15 | "generators", 16 | "iterators", 17 | "lazy", 18 | "compose", 19 | "functional", 20 | "programming", 21 | "prelude" 22 | ], 23 | "author": "Mudit Ameta", 24 | "license": "MIT", 25 | "dependencies": { 26 | "auto-curry": "^0.2.0", 27 | "clone": "^1.0.0", 28 | "is-generator": "^1.0.0" 29 | }, 30 | "devDependencies": { 31 | "babel": "^4.6.0", 32 | "babel-eslint": "^3.0.1", 33 | "babelify": "^5.0.3", 34 | "browserify": "^8.1.3", 35 | "eslint": "^0.19.0", 36 | "mocha": "^2.1.0", 37 | "should": "^5.0.1", 38 | "uglify-js": "^2.4.16" 39 | }, 40 | "repository": { 41 | "type": "git", 42 | "url": "https://github.com/zeusdeux/lazit.git" 43 | }, 44 | "bugs": { 45 | "url": "https://github.com/zeusdeux/lazit/issues" 46 | }, 47 | "homepage": "https://github.com/zeusdeux/lazit" 48 | } 49 | -------------------------------------------------------------------------------- /src/es5/zip3.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var zip3 = regeneratorRuntime.mark( 4 | 5 | // zip3 :: [a] -> [b] -> [c] -> [(a, b, c)] 6 | function zip3(a, b, c) { 7 | var aIterator, bIterator, cIterator, aObj, bObj, cObj; 8 | return regeneratorRuntime.wrap(function zip3$(context$1$0) { 9 | while (1) switch (context$1$0.prev = context$1$0.next) { 10 | case 0: 11 | aIterator = a[Symbol.iterator](); 12 | bIterator = b[Symbol.iterator](); 13 | cIterator = c[Symbol.iterator](); 14 | aObj = aIterator.next(); 15 | bObj = bIterator.next(); 16 | cObj = cIterator.next(); 17 | 18 | case 6: 19 | if (!(!aObj.done && !bObj.done && !cObj.done)) { 20 | context$1$0.next = 14; 21 | break; 22 | } 23 | 24 | context$1$0.next = 9; 25 | return [aObj.value, bObj.value, cObj.value]; 26 | 27 | case 9: 28 | aObj = aIterator.next(); 29 | bObj = bIterator.next(); 30 | cObj = cIterator.next(); 31 | context$1$0.next = 6; 32 | break; 33 | 34 | case 14: 35 | case "end": 36 | return context$1$0.stop(); 37 | } 38 | }, zip3, this); 39 | }); 40 | var cu = require("auto-curry"); 41 | 42 | module.exports = cu(zip3); -------------------------------------------------------------------------------- /test/concat.test.js: -------------------------------------------------------------------------------- 1 | require('should'); 2 | 3 | var concat = require('../src/esnext/concat'); 4 | var take = require('../src/esnext/take'); 5 | var repeat = require('../src/esnext/repeat'); 6 | 7 | describe('lazit#concat', function() { 8 | it('normal operation check', function() { 9 | var res; 10 | 11 | res = [...concat([1,2,3,4], [5,6,7,8])]; 12 | res.should.eql([1,2,3,4,5,6,7,8]); 13 | }); 14 | it('auto-curry check', function() { 15 | var res, c; 16 | 17 | c = concat([...take(4, repeat('a'))]); // auto-curry check 18 | 19 | res = [...c([1,2,3,4])]; 20 | res.should.eql(['a','a','a','a',1,2,3,4]); 21 | }); 22 | it('custom iterator check', function() { 23 | var res; 24 | 25 | function* customIterator(){ 26 | yield 1; 27 | yield 'a'; 28 | yield 'b'; 29 | yield 10; 30 | } 31 | 32 | res = [...concat(['x'], customIterator())]; 33 | res.should.eql(['x', 1, 'a', 'b', 10]); 34 | }); 35 | it('empty list check', function() { 36 | var res; 37 | 38 | res = [...concat([],[])]; 39 | res.should.eql([]); 40 | 41 | res = [...concat([], [1])]; 42 | res.should.eql([1]); 43 | 44 | res = [...concat([1], [])]; 45 | res.should.eql([1]); 46 | }); 47 | }); 48 | -------------------------------------------------------------------------------- /test/init.test.js: -------------------------------------------------------------------------------- 1 | require('should'); 2 | 3 | var map = require('../src/esnext/map'); 4 | var init = require('../src/esnext/init'); 5 | var take = require('../src/esnext/take'); 6 | var iterate = require('../src/esnext/iterate'); 7 | 8 | 9 | describe('lazit#init', function() { 10 | it('normal operation check', function() { 11 | var res; 12 | 13 | res = [...init([1,2,3,4])]; 14 | res.should.eql([1,2,3]); 15 | 16 | res = [...init(map(v => ++v, take(5, iterate(v => v*v, 2))))]; 17 | res.should.eql([3,5,17,257]); 18 | }); 19 | it('custom iterator check', function() { 20 | var res; 21 | 22 | function* customIterator(){ 23 | yield 'a'; 24 | yield 1; 25 | yield 'b'; 26 | yield 2; 27 | } 28 | 29 | function* delegator(){ 30 | yield* customIterator(); 31 | yield 'c'; 32 | yield 3; 33 | return 4; 34 | } 35 | 36 | res = [...init(delegator())]; 37 | res.should.eql(['a', 1, 'b', 2, 'c']); 38 | }); 39 | it('empty list check', function(done) { 40 | try { 41 | // throw mofo 42 | for (let x of init([])) console.log(x); 43 | } 44 | catch(e){ 45 | e.message.should.eql('Cannot get init of empty list'); 46 | done(); 47 | } 48 | }); 49 | }); 50 | -------------------------------------------------------------------------------- /src/es5/init.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var init = regeneratorRuntime.mark( 4 | 5 | // init :: [a] -> [a] 6 | // [a] should be non-empty 7 | function init(a) { 8 | var _getIteratorAndObj, xsIt, itObj, nextObj; 9 | 10 | return regeneratorRuntime.wrap(function init$(context$1$0) { 11 | while (1) switch (context$1$0.prev = context$1$0.next) { 12 | case 0: 13 | _getIteratorAndObj = getIteratorAndObj(a); 14 | xsIt = _getIteratorAndObj.xsIt; 15 | itObj = _getIteratorAndObj.itObj; 16 | nextObj = xsIt.next(); 17 | 18 | if (!itObj.done) { 19 | context$1$0.next = 6; 20 | break; 21 | } 22 | 23 | throw new Error("Cannot get init of empty list"); 24 | 25 | case 6: 26 | if (nextObj.done) { 27 | context$1$0.next = 13; 28 | break; 29 | } 30 | 31 | context$1$0.next = 9; 32 | return itObj.value; 33 | 34 | case 9: 35 | itObj = nextObj; 36 | nextObj = xsIt.next(); 37 | context$1$0.next = 6; 38 | break; 39 | 40 | case 13: 41 | case "end": 42 | return context$1$0.stop(); 43 | } 44 | }, init, this); 45 | }); 46 | var getIteratorAndObj = require("./util").getIteratorAndObj; 47 | 48 | module.exports = init; -------------------------------------------------------------------------------- /src/es5/zipWith3.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var zipWith3 = regeneratorRuntime.mark( 4 | 5 | // zipWith3 :: (a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d] 6 | function zipWith3(f, a, b, c) { 7 | var aIterator, bIterator, cIterator, aObj, bObj, cObj; 8 | return regeneratorRuntime.wrap(function zipWith3$(context$1$0) { 9 | while (1) switch (context$1$0.prev = context$1$0.next) { 10 | case 0: 11 | aIterator = a[Symbol.iterator](); 12 | bIterator = b[Symbol.iterator](); 13 | cIterator = c[Symbol.iterator](); 14 | aObj = aIterator.next(); 15 | bObj = bIterator.next(); 16 | cObj = cIterator.next(); 17 | 18 | case 6: 19 | if (!(!aObj.done && !bObj.done && !cObj.done)) { 20 | context$1$0.next = 14; 21 | break; 22 | } 23 | 24 | context$1$0.next = 9; 25 | return f(aObj.value, bObj.value, cObj.value); 26 | 27 | case 9: 28 | aObj = aIterator.next(); 29 | bObj = bIterator.next(); 30 | cObj = cIterator.next(); 31 | context$1$0.next = 6; 32 | break; 33 | 34 | case 14: 35 | case "end": 36 | return context$1$0.stop(); 37 | } 38 | }, zipWith3, this); 39 | }); 40 | var cu = require("auto-curry"); 41 | 42 | module.exports = cu(zipWith3); -------------------------------------------------------------------------------- /test/cycle.test.js: -------------------------------------------------------------------------------- 1 | require('should'); 2 | 3 | var take = require('../src/esnext/take'); 4 | var cycle = require('../src/esnext/cycle'); 5 | 6 | 7 | describe('lazit#cycle', function() { 8 | it('normal operation check', function() { 9 | var res; 10 | 11 | res = [...take(5, cycle([1,2]))]; 12 | res.should.eql([1,2,1,2,1]); 13 | }); 14 | it('custom iterator check', function() { 15 | var res; 16 | 17 | function* customIterator(){ 18 | yield 1; 19 | yield 2; 20 | yield* boom(); 21 | } 22 | function* boom(){ 23 | yield 3; 24 | yield 4; 25 | } 26 | // iterators/generators need to passed as is 27 | // cycle calls it and uses the iterator it returns 28 | // if you pass the iterator obj or generator obj here 29 | // then I have no way of restarting it once it ends 30 | // and I might need to iterate over it more than once 31 | // if you pull more elements out from it than it actually 32 | // yields 33 | res = [...take(5, cycle(customIterator))]; 34 | res.should.eql([1,2,3,4,1]); 35 | }); 36 | it('empty list check', function(done) { 37 | try { 38 | [...cycle([])]; 39 | } 40 | catch(e){ 41 | e.message.should.eql('Cannot cycle empty list/iterable'); 42 | done(); 43 | } 44 | }); 45 | }); 46 | -------------------------------------------------------------------------------- /src/es5/repeat.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var repeat = regeneratorRuntime.mark( 4 | 5 | // repeat :: a -> [a] 6 | function repeat(a) { 7 | return regeneratorRuntime.wrap(function repeat$(context$1$0) { 8 | while (1) switch (context$1$0.prev = context$1$0.next) { 9 | case 0: 10 | if (!true) { 11 | context$1$0.next = 10; 12 | break; 13 | } 14 | 15 | if (isObject(a)) { 16 | context$1$0.next = 6; 17 | break; 18 | } 19 | 20 | context$1$0.next = 4; 21 | return a; 22 | 23 | case 4: 24 | context$1$0.next = 8; 25 | break; 26 | 27 | case 6: 28 | context$1$0.next = 8; 29 | return clone(a); 30 | 31 | case 8: 32 | context$1$0.next = 0; 33 | break; 34 | 35 | case 10: 36 | case "end": 37 | return context$1$0.stop(); 38 | } 39 | }, repeat, this); 40 | }); 41 | var clone = require("clone"); 42 | var isObject = require("./util").isObject; 43 | 44 | module.exports = repeat; 45 | 46 | // cloning since objects are basically pointers in js. 47 | // If I just `yield a` then all the elements in the resulting 48 | // list will contain reference to the same object and all hell 49 | // will break loose, it'll rain cows and horses, ketchup will 50 | // replace water and all the liquour in the world will disappear. 51 | // Saving your life here, man. -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "predef": [ 3 | "console", 4 | "describe", 5 | "it", 6 | "after", 7 | "afterEach", 8 | "before", 9 | "beforeEach" 10 | ], 11 | 12 | "browser": true, 13 | "couch": false, 14 | "devel": true, 15 | "jquery": false, 16 | "node": true, 17 | "phantom": false, 18 | 19 | "bitwise": false, 20 | "camelcase": true, 21 | "curly": false, 22 | "eqeqeq": true, 23 | "es3": false, 24 | "forin": false, 25 | "freeze": false, 26 | "immed": true, 27 | "indent": 2, 28 | "latedef": false, 29 | "newcap": true, 30 | "noarg": true, 31 | "noempty": false, 32 | "nonbsp": true, 33 | "nonew": true, 34 | "plusplus": false, 35 | "quotmark": "single", 36 | "undef": true, 37 | "unused": "vars", 38 | "strict": false, 39 | "trailing": true, 40 | 41 | "asi": false, 42 | "boss": true, 43 | "debug": false, 44 | "eqnull": true, 45 | "esnext": true, 46 | "evil": false, 47 | "expr": false, 48 | "funcscope": false, 49 | "globalstrict": false, 50 | "iterator": false, 51 | "lastsemic": false, 52 | "laxbreak": false, 53 | "laxcomma": false, 54 | "loopfunc": true, 55 | "multistr": false, 56 | "scripturl": false, 57 | "smarttabs": false, 58 | "shadow": false, 59 | "sub": false, 60 | "supernew": true, 61 | "validthis": false 62 | } 63 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # folders 2 | SRC = ./src 3 | TEST = ./test 4 | BUILD = ./build 5 | BIN = $(NODEMOD)/.bin 6 | NODEMOD = ./node_modules 7 | TEST = ./test 8 | 9 | # files 10 | MAIN = $(SRC)/index.js 11 | BROWSER = $(SRC)/browser.js 12 | MAPFILE = lazit.min.map 13 | 14 | all: eslint test $(BUILD)/lazit.min.js 15 | 16 | force: $(BUILD)/lazit.min.js 17 | 18 | eslint: 19 | $(BIN)/eslint $(SRC)/*.js $(SRC)/esnext/*.js 20 | 21 | test: 22 | # run test 23 | $(BIN)/mocha -r should -u bdd -b --compilers js:babel/register $(TEST)/*.js 24 | 25 | test-watch: 26 | $(BIN)/mocha -r should -u bdd -b --compilers js:babel/register $(TEST)/*.js -w 27 | 28 | $(BUILD)/lazit.min.js: $(BUILD)/lazit.js 29 | $(BIN)/uglifyjs $^ \ 30 | -o $@ \ 31 | -c -m \ 32 | --source-map $(BUILD)/$(MAPFILE) \ 33 | --source-map-root ../../ \ 34 | --source-map-url ./$(MAPFILE) \ 35 | --comments \ 36 | --stats 37 | 38 | $(BUILD)/lazit.js: $(MAIN) $(BROWSER) $(SRC)/esnext/*.js $(NODEMOD)/auto-curry/index.js $(NODEMOD)/clone/clone.js 39 | # generate es5 variants of the source 40 | $(BIN)/babel $(SRC)/esnext --out-dir $(SRC)/es5 41 | # todo: 42 | # gotta do something like below and provide readily usable 43 | # single functions in the browser 44 | # $(BIN)/browserify-directory $(SRC)/esnext $(SRC/) -t babelify 45 | $(BIN)/browserify -s lazit -e $(BROWSER) -o $@ -t babelify 46 | 47 | clean: 48 | rm -f $(BUILD)/* 49 | rm -f $(SRC)/es5/* 50 | 51 | watch: 52 | fswatch -o src/esnext/ src/index.js src/browser.js | xargs -n1 -I% make 53 | 54 | .PHONY: all force eslint test test-watch clean watch 55 | -------------------------------------------------------------------------------- /src/es5/zipN.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var zipN = regeneratorRuntime.mark( /*eslint no-loop-func:0*/ 4 | 5 | // zipN :: [a] -> [b] .... -> [n] -> [[a..n]] 6 | // zips n lists together 7 | // zipN does NOT auto-curry since there's no way of 8 | // knowing it's arity till it's called i.e., it's 9 | // variadic and hence cannot be curried in javascript 10 | function zipN() { 11 | for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { 12 | args[_key] = arguments[_key]; 13 | } 14 | 15 | var iterators, itObjs; 16 | return regeneratorRuntime.wrap(function zipN$(context$1$0) { 17 | while (1) switch (context$1$0.prev = context$1$0.next) { 18 | case 0: 19 | iterators = args.map(function (v) { 20 | return v[Symbol.iterator](); 21 | }); 22 | itObjs = iterators.map(function (v) { 23 | return v.next(); 24 | }); 25 | 26 | case 2: 27 | if (!(itObjs.filter(function (v) { 28 | return !v.done; 29 | }).length === itObjs.length)) { 30 | context$1$0.next = 8; 31 | break; 32 | } 33 | 34 | context$1$0.next = 5; 35 | return itObjs.map(function (v) { 36 | return v.value; 37 | }); 38 | 39 | case 5: 40 | itObjs = iterators.map(function (v) { 41 | return v.next(); 42 | }); 43 | context$1$0.next = 2; 44 | break; 45 | 46 | case 8: 47 | case "end": 48 | return context$1$0.stop(); 49 | } 50 | }, zipN, this); 51 | }); 52 | 53 | module.exports = zipN; -------------------------------------------------------------------------------- /test/span.test.js: -------------------------------------------------------------------------------- 1 | require('should'); 2 | 3 | var map = require('../src/esnext/map'); 4 | var take = require('../src/esnext/take'); 5 | var span = require('../src/esnext/span'); 6 | var iterate = require('../src/esnext/iterate'); 7 | 8 | describe('lazit#span', function() { 9 | it('normal operation check', function() { 10 | var res; 11 | var arr = [1, 2, 3, 4]; 12 | 13 | res = span(v => v < 4, map(v => ++v, [1, 2, 3, 4])); 14 | res.should.eql([[2,3],[4, 5]]); 15 | 16 | // input iterator mutation check 17 | res = span(v => v < 3, arr); 18 | res.should.eql([[1,2],[3, 4]]); 19 | arr.should.eql([1, 2, 3, 4]); //input array should remain unchanged 20 | 21 | // dropping more elements than in list 22 | res = span(v => v < 10, arr); 23 | res.should.eql([[1,2,3,4], []]); 24 | arr.should.eql([1, 2, 3, 4]); 25 | }); 26 | it('auto-curry check', function() { 27 | var res, m, t, s; 28 | 29 | m = map(v => v * v); 30 | t = take(4); 31 | s = span(v => v < 9); // auto-curry check 32 | 33 | res = s(t(m(iterate(v => v + 1, 1)))); 34 | res.should.eql([[1, 4],[9, 16]]); 35 | }); 36 | it('custom iterator check', function() { 37 | var res; 38 | 39 | function* customIterator() { 40 | yield 1; 41 | yield 'a'; 42 | yield 2; 43 | yield 'b'; 44 | } 45 | 46 | res = span(v => 'number' === typeof v, customIterator()); 47 | res.should.eql([[1],['a', 2, 'b']]); 48 | }); 49 | it('empty list check', function() { 50 | var res; 51 | 52 | res = span(() => true, []); 53 | res.should.eql([[],[]]); 54 | }); 55 | }); 56 | -------------------------------------------------------------------------------- /src/es5/zipWithN.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var zipWithN = regeneratorRuntime.mark( /*eslint no-loop-func:0*/ 4 | 5 | // zipWithN :: (a -> b -> .... -> n -> x) -> [a] -> [b] -> .... -> [n] -> [x] 6 | // applies a function to a each element in a zip of n lists and returns new list 7 | // zipWithN does NOT auto-curry since it's variadic 8 | function zipWithN(f) { 9 | for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { 10 | args[_key - 1] = arguments[_key]; 11 | } 12 | 13 | var iterators, itObjs, temp; 14 | return regeneratorRuntime.wrap(function zipWithN$(context$1$0) { 15 | while (1) switch (context$1$0.prev = context$1$0.next) { 16 | case 0: 17 | iterators = args.map(function (v) { 18 | return v[Symbol.iterator](); 19 | }); 20 | itObjs = iterators.map(function (v) { 21 | return v.next(); 22 | }); 23 | 24 | case 2: 25 | if (!(itObjs.filter(function (v) { 26 | return !v.done; 27 | }).length === itObjs.length)) { 28 | context$1$0.next = 9; 29 | break; 30 | } 31 | 32 | temp = itObjs.map(function (v) { 33 | return v.value; 34 | }); 35 | context$1$0.next = 6; 36 | return f.apply(null, temp); 37 | 38 | case 6: 39 | itObjs = iterators.map(function (v) { 40 | return v.next(); 41 | }); 42 | context$1$0.next = 2; 43 | break; 44 | 45 | case 9: 46 | case "end": 47 | return context$1$0.stop(); 48 | } 49 | }, zipWithN, this); 50 | }); 51 | 52 | module.exports = zipWithN; -------------------------------------------------------------------------------- /test/spanInv.test.js: -------------------------------------------------------------------------------- 1 | require('should'); 2 | 3 | var map = require('../src/esnext/map'); 4 | var take = require('../src/esnext/take'); 5 | var spanInv = require('../src/esnext/spanInv'); 6 | var iterate = require('../src/esnext/iterate'); 7 | 8 | describe('lazit#spanInv', function() { 9 | it('normal operation check', function() { 10 | var res; 11 | var arr = [1, 2, 3, 4]; 12 | 13 | res = spanInv(v => v > 4, map(v => ++v, [1, 2, 3, 4])); 14 | res.should.eql([[2, 3, 4],[5]]); 15 | 16 | // input iterator mutation check 17 | res = spanInv(v => v > 3, arr); 18 | res.should.eql([[1, 2, 3],[4]]); 19 | arr.should.eql([1, 2, 3, 4]); //input array should remain unchanged 20 | 21 | // dropping more elements than in list 22 | res = spanInv(v => v < 10, arr); 23 | res.should.eql([[], [1, 2, 3, 4]]); 24 | arr.should.eql([1, 2, 3, 4]); 25 | }); 26 | it('auto-curry check', function() { 27 | var res, m, t, s; 28 | 29 | m = map(v => v * v); 30 | t = take(4); 31 | s = spanInv(v => v > 9); // auto-curry check 32 | 33 | res = s(t(m(iterate(v => v + 1, 1)))); 34 | res.should.eql([[1, 4, 9],[16]]); 35 | }); 36 | it('custom iterator check', function() { 37 | var res; 38 | 39 | function* customIterator() { 40 | yield 1; 41 | yield 'a'; 42 | yield 2; 43 | yield 'b'; 44 | } 45 | 46 | res = spanInv(v => 'number' !== typeof v, customIterator()); 47 | res.should.eql([[1],['a', 2, 'b']]); 48 | }); 49 | it('empty list check', function() { 50 | var res; 51 | 52 | res = spanInv(() => true, []); 53 | res.should.eql([[],[]]); 54 | }); 55 | }); 56 | -------------------------------------------------------------------------------- /test/scanl1.test.js: -------------------------------------------------------------------------------- 1 | require('should'); 2 | 3 | var map = require('../src/esnext/map'); 4 | var take = require('../src/esnext/take'); 5 | var scanl1 = require('../src/esnext/scanl1'); 6 | var repeat = require('../src/esnext/repeat'); 7 | var iterate = require('../src/esnext/iterate'); 8 | 9 | describe('lazit#scanl1', function() { 10 | it('normal operation check', function() { 11 | var res; 12 | 13 | res = [...scanl1((acc, el) => acc + el, [0,1,2,3,4])]; 14 | res.should.eql([0,1,3,6,10]); 15 | 16 | res = [...scanl1((acc, el) => acc + el, map(v => ++v, take(5, iterate(v => v*v, 2))))]; 17 | res.should.eql([3,8,25,282,65819]); 18 | }); 19 | it('auto-curry check', function() { 20 | var res; 21 | var m = scanl1((a,b) => a+b); // auto-curry check 22 | var n = scanl1((a,b) => 0); // auto-curry check 23 | 24 | res = [...m(take(5, repeat(1)))]; 25 | res.should.eql([1,2,3,4,5]); 26 | 27 | res = [...n([1,2,3,4])]; 28 | res.should.eql([1,0,0,0,]); 29 | }); 30 | it('custom iterator check', function() { 31 | var res; 32 | var acc = []; 33 | 34 | function* customIterator(){ 35 | yield acc; 36 | yield 'a'; 37 | yield 'b'; 38 | yield 'c'; 39 | } 40 | 41 | res = [...scanl1((a,b) => { 42 | if ('string' === typeof b) { 43 | a.unshift(b); 44 | } 45 | return a; 46 | }, customIterator())]; 47 | 48 | res.should.eql([[],['a'],['b','a'],['c','b','a']]); 49 | acc.should.eql([]); 50 | }); 51 | it('empty list check', function() { 52 | var res; 53 | 54 | res = [...scanl1((a,b) => a+b, [])]; 55 | res.should.eql([]); 56 | }); 57 | }); 58 | -------------------------------------------------------------------------------- /test/splitAt.test.js: -------------------------------------------------------------------------------- 1 | require('should'); 2 | 3 | var map = require('../src/esnext/map'); 4 | var take = require('../src/esnext/take'); 5 | var iterate = require('../src/esnext/iterate'); 6 | var splitAt = require('../src/esnext/splitAt'); 7 | 8 | describe('lazit#splitAt', function() { 9 | it('normal operation check', function() { 10 | var res; 11 | var arr = [1,2,3,4]; 12 | 13 | res = splitAt(2, take(4, map(v => ++v, [1,2,3,4]))); 14 | res.should.eql([[2,3],[4,5]]); 15 | 16 | res = splitAt(1, take(1, map(v => ++v, [1,2,3,4]))); 17 | res.should.eql([[2], []]); 18 | 19 | // input iterator mutation check 20 | res = splitAt(2, arr); 21 | res.should.eql([[1,2], [3,4]]); 22 | arr.should.eql([1,2,3,4]); //input array should remain unchanged 23 | 24 | // splitAtping more elements than in list 25 | res = splitAt(5, arr); 26 | res.should.eql([[1,2,3,4],[]]); 27 | arr.should.eql([1,2,3,4]); 28 | }); 29 | it('auto-curry check', function() { 30 | var res, m, t, d; 31 | 32 | m = map(v => v*v); 33 | t = take(4); 34 | d = splitAt(2); // auto-curry check 35 | 36 | res = d(t(m(iterate(v => v+1, 1)))); 37 | res.should.eql([[1,4], [9,16]]); 38 | }); 39 | it('custom iterator check', function() { 40 | var res; 41 | 42 | function* customIterator(){ 43 | yield 1; 44 | yield 'a'; 45 | yield 2; 46 | yield 'b'; 47 | } 48 | 49 | res = splitAt(3, customIterator()); 50 | res.should.eql([[1,'a',2], ['b']]); 51 | }); 52 | it('empty list check', function() { 53 | var res; 54 | 55 | res = splitAt(4, []); 56 | res.should.eql([[],[]]); 57 | }); 58 | }); 59 | -------------------------------------------------------------------------------- /test/foldl1.test.js: -------------------------------------------------------------------------------- 1 | require('should'); 2 | 3 | var map = require('../src/esnext/map'); 4 | var take = require('../src/esnext/take'); 5 | var foldl1 = require('../src/esnext/foldl1'); 6 | var repeat = require('../src/esnext/repeat'); 7 | var filter = require('../src/esnext/filter'); 8 | var iterate = require('../src/esnext/iterate'); 9 | 10 | describe('lazit#foldl1', function() { 11 | it('normal operation check', function() { 12 | var res; 13 | 14 | res = foldl1((acc, el) => acc + el, [1,2,3,4]); 15 | res.should.eql(10); 16 | 17 | res = foldl1((acc, el) => acc + el, map(v => ++v, take(5, iterate(v => v*v, 2)))); 18 | res.should.eql(65819); 19 | }); 20 | it('auto-curry check', function() { 21 | var res; 22 | var m = foldl1((a,b) => a+b); // auto-curry check 23 | 24 | res = m(take(5, repeat(1))); 25 | res.should.eql(5); 26 | }); 27 | it('custom iterator check', function() { 28 | var res; 29 | var acc = []; 30 | 31 | function* customIterator(){ 32 | yield acc; 33 | yield 'a'; 34 | yield 1; 35 | yield 'b'; 36 | yield 2; 37 | } 38 | 39 | function* delegator(){ 40 | yield* customIterator(); 41 | yield 'c'; 42 | yield 3; 43 | return 4; 44 | } 45 | 46 | res = foldl1((a,b) => { 47 | if ('string' === typeof b) { 48 | a.push(b); 49 | } 50 | return a; 51 | }, delegator()); 52 | res.should.eql([...filter(v => 'string' === typeof v, delegator())]); 53 | acc.should.eql([]); 54 | }); 55 | 56 | it('empty list check', function() { 57 | foldl1.bind(null, (a,b) => a+b, []).should.throw('Cannot apply foldl1 to an empty list'); 58 | }); 59 | }); 60 | -------------------------------------------------------------------------------- /test/zip.test.js: -------------------------------------------------------------------------------- 1 | require('should'); 2 | 3 | var zip = require('../src/esnext/zip'); 4 | var map = require('../src/esnext/map'); 5 | var take = require('../src/esnext/take'); 6 | var repeat = require('../src/esnext/repeat'); 7 | var iterate = require('../src/esnext/iterate'); 8 | 9 | 10 | describe('lazit#zip', function() { 11 | it('normal operation check', function() { 12 | var res; 13 | 14 | res = [...zip([1,2,3], [5,6])]; 15 | res.should.eql([[1,5], [2,6]]); 16 | 17 | res = [...zip([0,1,2,3], map(v => ++v, take(5, iterate(v => v*v, 2))))]; 18 | res.should.eql([[0,3], [1,5], [2,17], [3,257]]); 19 | 20 | res = [...zip(['a','b'], iterate(v => v + 1, 0))]; 21 | res.should.eql([['a',0], ['b',1]]); 22 | }); 23 | it('auto-curry check', function() { 24 | var res; 25 | var z = zip(['a',1]); // auto-curry check 26 | 27 | res = [...z(take(5, repeat(1)))]; 28 | res.should.eql([['a',1], [1,1]]); 29 | 30 | }); 31 | it('custom iterator check', function() { 32 | var res; 33 | var acc = []; 34 | 35 | function* customIterator(){ 36 | yield 'a'; 37 | yield 1; 38 | yield 'b'; 39 | yield 2; 40 | } 41 | 42 | function* customIterator2(){ 43 | yield 'c'; 44 | yield 3; 45 | return 4; 46 | } 47 | 48 | res = [...zip(customIterator(), customIterator2())]; 49 | res.should.eql([['a','c'], [1,3]]); 50 | acc.should.eql([]); 51 | }); 52 | 53 | it('empty list check', function() { 54 | var res; 55 | 56 | res = [...zip([1,2,3], [])]; 57 | res.should.eql([]); 58 | res = [...zip([], [])]; 59 | res.should.eql([]); 60 | res = [...zip([], [1,2,3])]; 61 | res.should.eql([]); 62 | }); 63 | }); 64 | -------------------------------------------------------------------------------- /test/scanl.test.js: -------------------------------------------------------------------------------- 1 | require('should'); 2 | 3 | var map = require('../src/esnext/map'); 4 | var take = require('../src/esnext/take'); 5 | var scanl = require('../src/esnext/scanl'); 6 | var repeat = require('../src/esnext/repeat'); 7 | var iterate = require('../src/esnext/iterate'); 8 | 9 | describe('lazit#scanl', function() { 10 | it('normal operation check', function() { 11 | var res; 12 | 13 | res = [...scanl((acc, el) => acc + el, 0, [1,2,3,4])]; 14 | res.should.eql([0,1,3,6,10]); 15 | 16 | res = [...scanl((acc, el) => acc + el, 0, map(v => ++v, take(5, iterate(v => v*v, 2))))]; 17 | res.should.eql([0,3,8,25,282,65819]); 18 | }); 19 | it('auto-curry check', function() { 20 | var res; 21 | var m = scanl((a,b) => a+b); // auto-curry check 22 | var n = scanl((a,b) => 0, 0); // auto-curry check 23 | 24 | res = [...m(0, take(5, repeat(1)))]; 25 | res.should.eql([0,1,2,3,4,5]); 26 | 27 | res = [...n([1,2,3,4])]; 28 | res.should.eql([0,0,0,0,0]); 29 | }); 30 | it('custom iterator check', function() { 31 | var res; 32 | var acc = []; 33 | 34 | function* customIterator(){ 35 | yield 'a'; 36 | yield 'b'; 37 | yield 'c'; 38 | } 39 | 40 | res = [...scanl((a,b) => { 41 | if ('string' === typeof b) { 42 | a.unshift(b); 43 | } 44 | return a; 45 | }, acc, customIterator())]; 46 | 47 | res.should.eql([[],['a'],['b','a'],['c','b','a']]); 48 | acc.should.eql([]); 49 | }); 50 | it('empty list check', function() { 51 | var res; 52 | 53 | res = [...scanl((a,b) => a+b, 0, [])]; 54 | res.should.eql([0]); 55 | res = [...scanl((a,b) => a+b, 'abcd', [])]; 56 | res.should.eql(['abcd']); 57 | }); 58 | }); 59 | -------------------------------------------------------------------------------- /test/drop.test.js: -------------------------------------------------------------------------------- 1 | require('should'); 2 | 3 | var map = require('../src/esnext/map'); 4 | var drop = require('../src/esnext/drop'); 5 | var take = require('../src/esnext/take'); 6 | var iterate = require('../src/esnext/iterate'); 7 | 8 | describe('lazit#drop', function() { 9 | it('normal operation check', function() { 10 | var res; 11 | var arr = [1, 2, 3, 4]; 12 | 13 | res = [...drop(2, map(v => ++v, [1, 2, 3, 4]))]; 14 | res.should.eql([4, 5]); 15 | 16 | // dropping from an infinite list and taking from the 17 | // non dropped items from the resultant infinite list 18 | res = [...take(1, drop(2, map(v => ++v, [1, 2, 3, 4])))]; 19 | res.should.eql([4]); 20 | 21 | // input iterator mutation check 22 | res = [...drop(2, arr)]; 23 | res.should.eql([3, 4]); 24 | arr.should.eql([1, 2, 3, 4]); //input array should remain unchanged 25 | 26 | // dropping more elements than in list 27 | res = [...drop(5, arr)]; 28 | res.should.eql([]); 29 | arr.should.eql([1, 2, 3, 4]); 30 | 31 | 32 | }); 33 | it('auto-curry check', function() { 34 | var res, m, t, d; 35 | 36 | m = map(v => v * v); 37 | t = take(4); 38 | d = drop(2); // auto-curry check 39 | 40 | res = [...d(t(m(iterate(v => v + 1, 1))))]; 41 | res.should.eql([9, 16]); 42 | }); 43 | it('custom iterator check', function() { 44 | var res; 45 | 46 | function* customIterator() { 47 | yield 1; 48 | yield 'a'; 49 | yield 2; 50 | yield 'b'; 51 | } 52 | 53 | res = [...drop(3, customIterator())]; 54 | res.should.eql(['b']); 55 | }); 56 | it('empty list check', function() { 57 | var res; 58 | 59 | res = [...drop(4, [])]; 60 | res.should.eql([]); 61 | }); 62 | }); 63 | -------------------------------------------------------------------------------- /test/foldr1.test.js: -------------------------------------------------------------------------------- 1 | require('should'); 2 | 3 | var map = require('../src/esnext/map'); 4 | var take = require('../src/esnext/take'); 5 | var foldr1 = require('../src/esnext/foldr1'); 6 | var repeat = require('../src/esnext/repeat'); 7 | var filter = require('../src/esnext/filter'); 8 | var iterate = require('../src/esnext/iterate'); 9 | var reverse = require('../src/esnext/reverse'); 10 | 11 | 12 | describe('lazit#foldr1', function() { 13 | it('normal operation check', function() { 14 | var res; 15 | 16 | res = foldr1((el, acc) => el / acc, [1,2,3,4]); 17 | res.should.eql(0.375); 18 | 19 | res = foldr1((el, acc) => el / acc, map(v => ++v, take(5, iterate(v => v*v, 2)))); 20 | res.should.eql(2601.0793774319063); 21 | }); 22 | it('auto-curry check', function() { 23 | var res; 24 | var m = foldr1((a,b) => a+b); // auto-curry check 25 | 26 | res = m(take(5, repeat(1))); 27 | res.should.eql(5); 28 | }); 29 | it('custom iterator check', function() { 30 | var res; 31 | var acc = []; 32 | 33 | function* customIterator(){ 34 | yield 'a'; 35 | yield 1; 36 | yield 'b'; 37 | yield 2; 38 | } 39 | 40 | function* delegator(){ 41 | yield* customIterator(); 42 | yield 'c'; 43 | yield 3; 44 | yield acc; 45 | return 4; 46 | } 47 | 48 | res = foldr1((el, acc) => { 49 | if ('string' === typeof el) acc.push(el); 50 | return acc; 51 | }, delegator()); 52 | res.should.eql(reverse(filter(v => 'string' === typeof v, delegator()))); 53 | acc.should.eql([]); 54 | }); 55 | 56 | it('empty list check', function() { 57 | foldr1.bind(null, (a,b) => a+b, []).should.throw('Cannot apply foldr1 to an empty list'); 58 | }); 59 | }); 60 | -------------------------------------------------------------------------------- /test/take.test.js: -------------------------------------------------------------------------------- 1 | require('should'); 2 | 3 | var map = require('../src/esnext/map'); 4 | var drop = require('../src/esnext/drop'); 5 | var take = require('../src/esnext/take'); 6 | var iterate = require('../src/esnext/iterate'); 7 | 8 | describe('lazit#take', function() { 9 | it('normal operation check', function() { 10 | var res; 11 | var arr = [1, 2, 3, 4]; 12 | 13 | res = [...take(2, map(v => ++v, [1, 2, 3, 4]))]; 14 | res.should.eql([2, 3]); 15 | 16 | // dropping from an infinite list and taking from the 17 | // non dropped items from the resultant infinite list 18 | res = [...take(1, drop(2, map(v => ++v, [1, 2, 3, 4])))]; 19 | res.should.eql([4]); 20 | 21 | // input iterator mutation check 22 | res = [...take(2, arr)]; 23 | res.should.eql([1, 2]); 24 | arr.should.eql([1, 2, 3, 4]); //input array should remain unchanged 25 | 26 | // dropping more elements than in list 27 | res = [...take(5, arr)]; 28 | res.should.eql([1, 2, 3, 4]); 29 | arr.should.eql([1, 2, 3, 4]); 30 | }); 31 | it('auto-curry check', function() { 32 | var res, m, t, d; 33 | 34 | m = map(v => v * v); 35 | t = take(4); // auto-curry check 36 | d = drop(2); 37 | 38 | res = [...t(d(m(iterate(v => v + 1, 1))))]; 39 | res.should.eql([9, 16, 25, 36]); 40 | }); 41 | it('custom iterator check', function() { 42 | var res; 43 | 44 | function* customIterator() { 45 | yield 1; 46 | yield 'a'; 47 | yield 2; 48 | yield 'b'; 49 | } 50 | 51 | res = [...take(3, customIterator())]; 52 | res.should.eql([1, 'a', 2]); 53 | }); 54 | it('empty list check', function() { 55 | var res; 56 | 57 | res = [...take(4, [])]; 58 | res.should.eql([]); 59 | }); 60 | }); 61 | -------------------------------------------------------------------------------- /test/zipWith.test.js: -------------------------------------------------------------------------------- 1 | require('should'); 2 | 3 | var map = require('../src/esnext/map'); 4 | var take = require('../src/esnext/take'); 5 | var repeat = require('../src/esnext/repeat'); 6 | var iterate = require('../src/esnext/iterate'); 7 | var zipWith = require('../src/esnext/zipWith'); 8 | 9 | 10 | describe('lazit#zipWith', function() { 11 | it('normal operation check', function() { 12 | var res; 13 | 14 | res = [...zipWith((a,b) => a + b, [1,2,3], [5,6])]; 15 | res.should.eql([6,8]); 16 | 17 | res = [...zipWith((a,b) => a + b, [0,1,2,3], map(v => ++v, take(5, iterate(v => v*v, 2))))]; 18 | res.should.eql([3, 6, 19, 260]); 19 | 20 | res = [...zipWith((a,b) => a + b, ['a','b'], iterate(v => v + 1, 0))]; 21 | res.should.eql(['a0', 'b1']); 22 | }); 23 | it('auto-curry check', function() { 24 | var res; 25 | var z = zipWith((a,_) => a); 26 | var z2 = zipWith((a,b) => a + b, ['a',1]); // auto-curry check 27 | 28 | res = [...z([1,2,3], take(5, repeat(1)))]; 29 | res.should.eql([1,2,3]); 30 | 31 | res = [...z2([0])]; 32 | res.should.eql(['a0']); 33 | }); 34 | it('custom iterator check', function() { 35 | var res; 36 | var acc = ['c', 3]; 37 | 38 | function* customIterator(){ 39 | yield 'a'; 40 | yield 1; 41 | yield 'b'; 42 | yield 2; 43 | } 44 | 45 | res = [...zipWith((a,b) => a + ' dude ' + b, customIterator(), acc)]; 46 | res.should.eql(['a dude c', '1 dude 3']); 47 | acc.should.eql(['c', 3]); 48 | }); 49 | 50 | it('empty list check', function() { 51 | var res; 52 | var f = (a,b) => true; 53 | 54 | res = [...zipWith(f, [1,2,3], [])]; 55 | res.should.eql([]); 56 | res = [...zipWith(f, [], [])]; 57 | res.should.eql([]); 58 | res = [...zipWith(f, [], [1,2,3])]; 59 | res.should.eql([]); 60 | }); 61 | }); 62 | -------------------------------------------------------------------------------- /src/es5/unzip.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | // unzip :: [(a, b)] -> ([a], [b]) 4 | function unzip(a) { 5 | var res = [[], []]; 6 | var _iteratorNormalCompletion = true; 7 | var _didIteratorError = false; 8 | var _iteratorError = undefined; 9 | 10 | try { 11 | for (var _iterator = a[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { 12 | var x = _step.value; 13 | var _iteratorNormalCompletion2 = true; 14 | var _didIteratorError2 = false; 15 | var _iteratorError2 = undefined; 16 | 17 | try { 18 | for (var _iterator2 = x[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { 19 | var y = _step2.value; 20 | 21 | if (2 !== x.length) throw new SyntaxError("unzip expects a tuple to have exactly two elements"); 22 | var curr = res.shift(); 23 | 24 | curr.push(y); 25 | res.push(curr); 26 | } 27 | } catch (err) { 28 | _didIteratorError2 = true; 29 | _iteratorError2 = err; 30 | } finally { 31 | try { 32 | if (!_iteratorNormalCompletion2 && _iterator2["return"]) { 33 | _iterator2["return"](); 34 | } 35 | } finally { 36 | if (_didIteratorError2) { 37 | throw _iteratorError2; 38 | } 39 | } 40 | } 41 | } 42 | } catch (err) { 43 | _didIteratorError = true; 44 | _iteratorError = err; 45 | } finally { 46 | try { 47 | if (!_iteratorNormalCompletion && _iterator["return"]) { 48 | _iterator["return"](); 49 | } 50 | } finally { 51 | if (_didIteratorError) { 52 | throw _iteratorError; 53 | } 54 | } 55 | } 56 | 57 | return res; 58 | } 59 | 60 | module.exports = unzip; -------------------------------------------------------------------------------- /test/foldl.test.js: -------------------------------------------------------------------------------- 1 | require('should'); 2 | 3 | var map = require('../src/esnext/map'); 4 | var take = require('../src/esnext/take'); 5 | var foldl = require('../src/esnext/foldl'); 6 | var repeat = require('../src/esnext/repeat'); 7 | var filter = require('../src/esnext/filter'); 8 | var iterate = require('../src/esnext/iterate'); 9 | 10 | describe('lazit#foldl', function() { 11 | it('normal operation check', function() { 12 | var res; 13 | 14 | res = foldl((acc, el) => acc + el, 0, [1,2,3,4]); 15 | res.should.eql(10); 16 | 17 | res = foldl((acc, el) => acc + el, 0, map(v => ++v, take(5, iterate(v => v*v, 2)))); 18 | res.should.eql(65819); 19 | }); 20 | it('auto-curry check', function() { 21 | var res; 22 | var m = foldl((a,b) => a+b); // auto-curry check 23 | var n = foldl((a,b) => 0, 0); // auto-curry check 24 | 25 | res = m(0, take(5, repeat(1))); 26 | res.should.eql(5); 27 | 28 | res = n([1,2,3,4]); 29 | res.should.eql(0); 30 | }); 31 | it('custom iterator check', function() { 32 | var res; 33 | var acc = []; 34 | 35 | function* customIterator(){ 36 | yield 'a'; 37 | yield 1; 38 | yield 'b'; 39 | yield 2; 40 | } 41 | 42 | function* delegator(){ 43 | yield* customIterator(); 44 | yield 'c'; 45 | yield 3; 46 | return 4; 47 | } 48 | 49 | res = foldl((a,b) => { 50 | if ('string' === typeof b) { 51 | a.push(b); 52 | } 53 | return a; 54 | }, acc, delegator()); 55 | res.should.eql([...filter(v => 'string' === typeof v, delegator())]); 56 | acc.should.eql([]); 57 | }); 58 | 59 | it('empty list check', function() { 60 | var res; 61 | 62 | res = foldl((a,b) => a+b, 0, []); 63 | res.should.eql(0); 64 | res = foldl((a,b) => a+b, 'abcd', []); 65 | res.should.eql('abcd'); 66 | }); 67 | }); 68 | -------------------------------------------------------------------------------- /test/dropWhile.test.js: -------------------------------------------------------------------------------- 1 | require('should'); 2 | 3 | var map = require('../src/esnext/map'); 4 | var take = require('../src/esnext/take'); 5 | var iterate = require('../src/esnext/iterate'); 6 | var dropWhile = require('../src/esnext/dropWhile'); 7 | 8 | describe('lazit#dropWhile', function() { 9 | it('normal operation check', function() { 10 | var res; 11 | var arr = [1, 2, 3, 4]; 12 | 13 | res = [...dropWhile(v => v < 4, map(v => ++v, [1, 2, 3, 4]))]; 14 | res.should.eql([4, 5]); 15 | 16 | // dropping from an infinite list and taking from the 17 | // non dropped items from the resultant infinite list 18 | res = [...take(1, dropWhile(v => v < 10, iterate(v => v + 1, 0)))]; 19 | res.should.eql([10]); 20 | 21 | // input iterator mutation check 22 | res = [...dropWhile(v => v < 3, arr)]; 23 | res.should.eql([3, 4]); 24 | arr.should.eql([1, 2, 3, 4]); //input array should remain unchanged 25 | 26 | // dropping more elements than in list 27 | res = [...dropWhile(v => v < 10, arr)]; 28 | res.should.eql([]); 29 | arr.should.eql([1, 2, 3, 4]); 30 | }); 31 | it('auto-curry check', function() { 32 | var res, m, t, d; 33 | 34 | m = map(v => v * v); 35 | t = take(4); 36 | d = dropWhile(v => v < 9); // auto-curry check 37 | 38 | res = [...d(t(m(iterate(v => v + 1, 1))))]; 39 | res.should.eql([9, 16]); 40 | }); 41 | it('custom iterator check', function() { 42 | var res; 43 | 44 | function* customIterator() { 45 | yield 1; 46 | yield 'a'; 47 | yield 2; 48 | yield 'b'; 49 | } 50 | 51 | res = [...dropWhile(v => 'number' === typeof v, customIterator())]; 52 | res.should.eql(['a', 2, 'b']); 53 | }); 54 | it('empty list check', function() { 55 | var res; 56 | 57 | res = [...dropWhile(() => true, [])]; 58 | res.should.eql([]); 59 | }); 60 | }); 61 | -------------------------------------------------------------------------------- /src/es5/unzip3.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | // unzip3 :: [(a, b, c)] -> ([a], [b], [c]) 4 | function unzip3(a) { 5 | var res = [[], [], []]; 6 | var _iteratorNormalCompletion = true; 7 | var _didIteratorError = false; 8 | var _iteratorError = undefined; 9 | 10 | try { 11 | for (var _iterator = a[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { 12 | var x = _step.value; 13 | var _iteratorNormalCompletion2 = true; 14 | var _didIteratorError2 = false; 15 | var _iteratorError2 = undefined; 16 | 17 | try { 18 | for (var _iterator2 = x[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { 19 | var y = _step2.value; 20 | 21 | if (3 !== x.length) throw new SyntaxError("unzip3 expects a tuple to have exactly three elements"); 22 | var curr = res.shift(); 23 | 24 | curr.push(y); 25 | res.push(curr); 26 | } 27 | } catch (err) { 28 | _didIteratorError2 = true; 29 | _iteratorError2 = err; 30 | } finally { 31 | try { 32 | if (!_iteratorNormalCompletion2 && _iterator2["return"]) { 33 | _iterator2["return"](); 34 | } 35 | } finally { 36 | if (_didIteratorError2) { 37 | throw _iteratorError2; 38 | } 39 | } 40 | } 41 | } 42 | } catch (err) { 43 | _didIteratorError = true; 44 | _iteratorError = err; 45 | } finally { 46 | try { 47 | if (!_iteratorNormalCompletion && _iterator["return"]) { 48 | _iterator["return"](); 49 | } 50 | } finally { 51 | if (_didIteratorError) { 52 | throw _iteratorError; 53 | } 54 | } 55 | } 56 | 57 | return res; 58 | } 59 | 60 | module.exports = unzip3; -------------------------------------------------------------------------------- /test/scanr.test.js: -------------------------------------------------------------------------------- 1 | require('should'); 2 | 3 | var map = require('../src/esnext/map'); 4 | var take = require('../src/esnext/take'); 5 | var scanr = require('../src/esnext/scanr'); 6 | var repeat = require('../src/esnext/repeat'); 7 | var iterate = require('../src/esnext/iterate'); 8 | 9 | 10 | describe('lazit#scanr', function() { 11 | it('normal operation check', function() { 12 | var res; 13 | 14 | res = scanr((el, acc) => el/acc, 1, [1,2,3,4]); 15 | res.should.eql([0.375,2.6666666666666665,0.75,4.0,1.0]); 16 | 17 | res = scanr((el, acc) => el/acc, 1, map(v => ++v, take(5, iterate(v => v*v, 2)))); 18 | res.should.eql([2601.0793774319063,1.153367338970622e-3,4335.1322957198445,3.9214489525001145e-3,65537.0,1.0]); 19 | }); 20 | it('auto-curry check', function() { 21 | var res; 22 | var m = scanr((a,b) => a+b); // auto-curry check 23 | var n = scanr((a,b) => 0, 0); // auto-curry check 24 | 25 | res = m(0, take(5, repeat(1))); 26 | res.should.eql([5,4,3,2,1,0]); 27 | 28 | res = n([1,2,3,4]); 29 | res.should.eql([0,0,0,0,0]); 30 | }); 31 | it('custom iterator check', function() { 32 | var res; 33 | var acc = []; 34 | 35 | function* customIterator(){ 36 | yield 'a'; 37 | yield 'b'; 38 | } 39 | 40 | function* delegator(){ 41 | yield* customIterator(); 42 | yield 'c'; 43 | } 44 | 45 | res = scanr((a,b) => { 46 | if ('string' === typeof a) { 47 | b.unshift(a); 48 | } 49 | return b; 50 | }, acc, delegator()); 51 | 52 | res.should.eql([['a','b','c'], ['b','c'], ['c'], []]); 53 | acc.should.eql([]); 54 | }); 55 | 56 | it('empty list check', function() { 57 | var res; 58 | 59 | res = scanr((a,b) => a+b, 0, []); 60 | res.should.eql([0]); 61 | res = scanr((a,b) => a+b, 'abcd', []); 62 | res.should.eql(['abcd']); 63 | }); 64 | }); 65 | -------------------------------------------------------------------------------- /test/takeWhile.test.js: -------------------------------------------------------------------------------- 1 | require('should'); 2 | 3 | var map = require('../src/esnext/map'); 4 | var drop = require('../src/esnext/drop'); 5 | var iterate = require('../src/esnext/iterate'); 6 | var takeWhile = require('../src/esnext/takeWhile'); 7 | 8 | describe('lazit#takeWhile', function() { 9 | it('normal operation check', function() { 10 | var res; 11 | var arr = [1, 2, 3, 4]; 12 | 13 | res = [...takeWhile(v => v < 3, map(v => ++v, [1, 2, 3, 4]))]; 14 | res.should.eql([2]); 15 | 16 | // dropping from an infinite list and taking from the 17 | // non dropped items from the resultant infinite list 18 | res = [...takeWhile(v => v < 5, drop(2, map(v => ++v, [1, 2, 3, 4])))]; 19 | res.should.eql([4]); 20 | 21 | // input iterator mutation check 22 | res = [...takeWhile(v => v > 0 && v < 3, arr)]; 23 | res.should.eql([1, 2]); 24 | arr.should.eql([1, 2, 3, 4]); //input array should remain unchanged 25 | 26 | // dropping more elements than in list 27 | res = [...takeWhile(() => true, arr)]; 28 | res.should.eql([1, 2, 3, 4]); 29 | arr.should.eql([1, 2, 3, 4]); 30 | }); 31 | it('auto-curry check', function() { 32 | var res, m, t, d; 33 | 34 | m = map(v => v * v); 35 | t = takeWhile(v => v < 37); // auto-curry check 36 | d = drop(2); 37 | 38 | res = [...t(d(m(iterate(v => v + 1, 1))))]; 39 | res.should.eql([9, 16, 25, 36]); 40 | }); 41 | it('custom iterator check', function() { 42 | var res; 43 | 44 | function* customIterator() { 45 | yield 1; 46 | yield 'a'; 47 | yield 2; 48 | yield 'b'; 49 | } 50 | 51 | res = [...takeWhile(v => 'string' === typeof v, customIterator())]; 52 | res.should.eql([]); 53 | }); 54 | it('empty list check', function() { 55 | var res; 56 | 57 | res = [...takeWhile(() => true, [])]; 58 | res.should.eql([]); 59 | }); 60 | }); 61 | -------------------------------------------------------------------------------- /test/foldr.test.js: -------------------------------------------------------------------------------- 1 | require('should'); 2 | 3 | var map = require('../src/esnext/map'); 4 | var take = require('../src/esnext/take'); 5 | var foldr = require('../src/esnext/foldr'); 6 | var repeat = require('../src/esnext/repeat'); 7 | var filter = require('../src/esnext/filter'); 8 | var iterate = require('../src/esnext/iterate'); 9 | var reverse = require('../src/esnext/reverse'); 10 | 11 | describe('lazit#foldr', function() { 12 | it('normal operation check', function() { 13 | var res; 14 | 15 | res = foldr((el, acc) => el/acc, 1, [1,2,3,4]); 16 | res.should.eql(0.375); 17 | 18 | res = foldr((el, acc) => el/acc, 1, map(v => ++v, take(5, iterate(v => v*v, 2)))); 19 | res.should.eql(2601.0793774319063); 20 | }); 21 | it('auto-curry check', function() { 22 | var res; 23 | var m = foldr((a,b) => a+b); // auto-curry check 24 | var n = foldr((a,b) => 0, 0); // auto-curry check 25 | 26 | res = m(0, take(5, repeat(1))); 27 | res.should.eql(5); 28 | 29 | res = n([1,2,3,4]); 30 | res.should.eql(0); 31 | }); 32 | it('custom iterator check', function() { 33 | var res; 34 | var acc = []; 35 | 36 | function* customIterator(){ 37 | yield 'a'; 38 | yield 1; 39 | yield 'b'; 40 | yield 2; 41 | } 42 | 43 | function* delegator(){ 44 | yield* customIterator(); 45 | yield 'c'; 46 | yield 3; 47 | return 4; 48 | } 49 | 50 | res = foldr((a,b) => { 51 | if ('string' === typeof a) { 52 | b.push(a); 53 | } 54 | return b; 55 | }, acc, delegator()); 56 | 57 | res.should.eql(reverse(filter(v => 'string' === typeof v, delegator()))); 58 | acc.should.eql([]); 59 | }); 60 | 61 | it('empty list check', function() { 62 | var res; 63 | 64 | res = foldr((a,b) => a+b, 0, []); 65 | res.should.eql(0); 66 | res = foldr((a,b) => a+b, 'abcd', []); 67 | res.should.eql('abcd'); 68 | }); 69 | }); 70 | -------------------------------------------------------------------------------- /test/zipWithN.test.js: -------------------------------------------------------------------------------- 1 | require('should'); 2 | 3 | var map = require('../src/esnext/map'); 4 | var take = require('../src/esnext/take'); 5 | var foldr = require('../src/esnext/foldr'); 6 | var repeat = require('../src/esnext/repeat'); 7 | var iterate = require('../src/esnext/iterate'); 8 | var zipWithN = require('../src/esnext/zipWithN'); 9 | 10 | 11 | describe('lazit#zipWithN', function() { 12 | it('normal operation check', function() { 13 | var res; 14 | 15 | res = [...zipWithN((a,b,c) => a + b + c, [1,2,3], [5,6], [0,1])]; 16 | res.should.eql([6,9]); 17 | 18 | res = [...zipWithN((a,b,c) => a + b + c, repeat(1), [0,1,2,3], map(v => ++v, take(5, iterate(v => v*v, 2))))]; 19 | res.should.eql([4, 7, 20, 261]); 20 | 21 | res = [...zipWithN((a,b,c) => a + b + c, [2,4], ['a','b'], iterate(v => v + 1, 0))]; 22 | res.should.eql(['2a0', '4b1']); 23 | 24 | res = [...zipWithN((...args) => foldr((a,b) => a + b, 0, args), [1,2,3])]; 25 | res.should.eql([1,2,3]); 26 | }); 27 | it('cannot auto-curry since zipWithN is variadic so no check. yay! \\o/', () => null); 28 | it('custom iterator check', function() { 29 | var res; 30 | var acc = ['c', 3]; 31 | 32 | function* customIterator(){ 33 | yield 'a'; 34 | yield 1; 35 | yield 'b'; 36 | yield 2; 37 | } 38 | 39 | res = [...zipWithN((a,b,c) => a + ' dude ' + b + ' what ' + c, customIterator(), acc, [20, 40])]; 40 | res.should.eql(['a dude c what 20', '1 dude 3 what 40']); 41 | acc.should.eql(['c', 3]); 42 | }); 43 | 44 | it('empty list check', function() { 45 | var res; 46 | var f = () => true; 47 | 48 | res = [...zipWithN(f, [1,2,3], [], [])]; 49 | res.should.eql([]); 50 | res = [...zipWithN(f, [], [], [])]; 51 | res.should.eql([]); 52 | res = [...zipWithN(f, [], [1,2,3], [])]; 53 | res.should.eql([]); 54 | res = [...zipWithN(f, [], [], [1,2,3])]; 55 | res.should.eql([]); 56 | }); 57 | }); 58 | -------------------------------------------------------------------------------- /test/zipN.test.js: -------------------------------------------------------------------------------- 1 | require('should'); 2 | 3 | var map = require('../src/esnext/map'); 4 | var zipN = require('../src/esnext/zipN'); 5 | var take = require('../src/esnext/take'); 6 | var iterate = require('../src/esnext/iterate'); 7 | 8 | 9 | describe('lazit#zipN', function() { 10 | it('normal operation check', function() { 11 | var res; 12 | 13 | res = [...zipN([1,2,3], [5,6], [7])]; 14 | res.should.eql([[1,5,7]]); 15 | 16 | res = [...zipN(['a','b','c','d'], [0,1,2,3], map(v => ++v, take(5, iterate(v => v*v, 2))))]; 17 | res.should.eql([['a',0,3], ['b',1,5], ['c',2,17], ['d',3,257]]); 18 | 19 | res = [...zipN(['a','b'], iterate(v => v + 1, 0), [100,200])]; 20 | res.should.eql([['a',0,100], ['b',1,200]]); 21 | 22 | res = [...zipN([1,2,3])]; 23 | res.should.eql([[1], [2], [3]]); 24 | 25 | res = [...zipN([1,2,3], [2,3,4], [3,4,5], [4,5,6], [5,6,7])]; 26 | res.should.eql([[1,2,3,4,5], [2,3,4,5,6], [3,4,5,6,7]]); 27 | }); 28 | it('cannot auto-curry since zipN is variadic so no check. yay! \\o/', function() { 29 | }); 30 | it('custom iterator check', function() { 31 | var res; 32 | var acc = ['dude', 'what']; 33 | 34 | function* customIterator(){ 35 | yield 'a'; 36 | yield 1; 37 | yield 'b'; 38 | yield 2; 39 | } 40 | 41 | function* customIterator2(){ 42 | yield 'c'; 43 | yield 3; 44 | return 4; 45 | } 46 | 47 | res = [...zipN(acc, customIterator(), customIterator2())]; 48 | res.should.eql([['dude','a','c'], ['what',1,3]]); 49 | acc.should.eql(['dude', 'what']); 50 | }); 51 | 52 | it('empty list check', function() { 53 | var res; 54 | 55 | res = [...zipN([1,2,3], [], [])]; 56 | res.should.eql([]); 57 | res = [...zipN([], [1,2,3], [])]; 58 | res.should.eql([]); 59 | res = [...zipN([], [], [1,2,3])]; 60 | res.should.eql([]); 61 | res = [...zipN([], [])]; 62 | res.should.eql([]); 63 | res = [...zipN([])]; 64 | res.should.eql([]); 65 | }); 66 | }); 67 | -------------------------------------------------------------------------------- /test/zip3.test.js: -------------------------------------------------------------------------------- 1 | require('should'); 2 | 3 | var map = require('../src/esnext/map'); 4 | var take = require('../src/esnext/take'); 5 | var zip3 = require('../src/esnext/zip3'); 6 | var repeat = require('../src/esnext/repeat'); 7 | var iterate = require('../src/esnext/iterate'); 8 | 9 | 10 | describe('lazit#zip3', function() { 11 | it('normal operation check', function() { 12 | var res; 13 | 14 | res = [...zip3([1,2,3], [5,6], [7])]; 15 | res.should.eql([[1,5,7]]); 16 | 17 | res = [...zip3(['a','b','c','d'], [0,1,2,3], map(v => ++v, take(5, iterate(v => v*v, 2))))]; 18 | res.should.eql([['a',0,3], ['b',1,5], ['c',2,17], ['d',3,257]]); 19 | 20 | res = [...zip3(['a','b'], iterate(v => v + 1, 0), [100,200])]; 21 | res.should.eql([['a',0,100], ['b',1,200]]); 22 | }); 23 | it('auto-curry check', function() { 24 | var res; 25 | var z = zip3(['a',1]); // auto-curry check 26 | var z2 = z([4,5]); 27 | 28 | res = [...z([20,30], take(5, repeat(1)))]; 29 | res.should.eql([['a',20,1], [1,30,1]]); 30 | 31 | res = [...z2([0])]; 32 | res.should.eql([['a', 4, 0]]); 33 | 34 | }); 35 | it('custom iterator check', function() { 36 | var res; 37 | var acc = ['dude', 'what']; 38 | 39 | function* customIterator(){ 40 | yield 'a'; 41 | yield 1; 42 | yield 'b'; 43 | yield 2; 44 | } 45 | 46 | function* customIterator2(){ 47 | yield 'c'; 48 | yield 3; 49 | return 4; 50 | } 51 | 52 | res = [...zip3(acc, customIterator(), customIterator2())]; 53 | res.should.eql([['dude','a','c'], ['what',1,3]]); 54 | acc.should.eql(['dude', 'what']); 55 | }); 56 | 57 | it('empty list check', function() { 58 | var res; 59 | 60 | res = [...zip3([1,2,3], [], [])]; 61 | res.should.eql([]); 62 | res = [...zip3([], [1,2,3], [])]; 63 | res.should.eql([]); 64 | res = [...zip3([], [], [1,2,3])]; 65 | res.should.eql([]); 66 | res = [...zip3([], [])]; 67 | res.should.eql([]); 68 | }); 69 | }); 70 | -------------------------------------------------------------------------------- /src/es5/map.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var map = regeneratorRuntime.mark( 4 | 5 | // map :: (a -> b) -> [a] -> [b] 6 | function map(f, a) { 7 | var _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, x; 8 | 9 | return regeneratorRuntime.wrap(function map$(context$1$0) { 10 | while (1) switch (context$1$0.prev = context$1$0.next) { 11 | case 0: 12 | _iteratorNormalCompletion = true; 13 | _didIteratorError = false; 14 | _iteratorError = undefined; 15 | context$1$0.prev = 3; 16 | _iterator = a[Symbol.iterator](); 17 | 18 | case 5: 19 | if (_iteratorNormalCompletion = (_step = _iterator.next()).done) { 20 | context$1$0.next = 12; 21 | break; 22 | } 23 | 24 | x = _step.value; 25 | context$1$0.next = 9; 26 | return f(x); 27 | 28 | case 9: 29 | _iteratorNormalCompletion = true; 30 | context$1$0.next = 5; 31 | break; 32 | 33 | case 12: 34 | context$1$0.next = 18; 35 | break; 36 | 37 | case 14: 38 | context$1$0.prev = 14; 39 | context$1$0.t9 = context$1$0["catch"](3); 40 | _didIteratorError = true; 41 | _iteratorError = context$1$0.t9; 42 | 43 | case 18: 44 | context$1$0.prev = 18; 45 | context$1$0.prev = 19; 46 | 47 | if (!_iteratorNormalCompletion && _iterator["return"]) { 48 | _iterator["return"](); 49 | } 50 | 51 | case 21: 52 | context$1$0.prev = 21; 53 | 54 | if (!_didIteratorError) { 55 | context$1$0.next = 24; 56 | break; 57 | } 58 | 59 | throw _iteratorError; 60 | 61 | case 24: 62 | return context$1$0.finish(21); 63 | 64 | case 25: 65 | return context$1$0.finish(18); 66 | 67 | case 26: 68 | case "end": 69 | return context$1$0.stop(); 70 | } 71 | }, map, this, [[3, 14, 18, 26], [19,, 21, 25]]); 72 | }); 73 | var cu = require("auto-curry"); 74 | 75 | module.exports = cu(map); -------------------------------------------------------------------------------- /src/es5/unzipN.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var _toConsumableArray = function (arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } else { return Array.from(arr); } }; 4 | 5 | var replicate = require("./replicate"); 6 | 7 | // unzipN :: [(a, b, .... , n)] -> ([a], [b], ...., [n]) 8 | function unzipN(a) { 9 | var res = undefined; 10 | 11 | var _iteratorNormalCompletion = true; 12 | var _didIteratorError = false; 13 | var _iteratorError = undefined; 14 | 15 | try { 16 | for (var _iterator = a[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { 17 | var x = _step.value; 18 | 19 | res = res || [].concat(_toConsumableArray(replicate(x.length, []))); 20 | var _iteratorNormalCompletion2 = true; 21 | var _didIteratorError2 = false; 22 | var _iteratorError2 = undefined; 23 | 24 | try { 25 | for (var _iterator2 = x[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { 26 | var y = _step2.value; 27 | 28 | var curr = res.shift(); 29 | 30 | curr.push(y); 31 | res.push(curr); 32 | } 33 | } catch (err) { 34 | _didIteratorError2 = true; 35 | _iteratorError2 = err; 36 | } finally { 37 | try { 38 | if (!_iteratorNormalCompletion2 && _iterator2["return"]) { 39 | _iterator2["return"](); 40 | } 41 | } finally { 42 | if (_didIteratorError2) { 43 | throw _iteratorError2; 44 | } 45 | } 46 | } 47 | } 48 | } catch (err) { 49 | _didIteratorError = true; 50 | _iteratorError = err; 51 | } finally { 52 | try { 53 | if (!_iteratorNormalCompletion && _iterator["return"]) { 54 | _iterator["return"](); 55 | } 56 | } finally { 57 | if (_didIteratorError) { 58 | throw _iteratorError; 59 | } 60 | } 61 | } 62 | 63 | return res || []; 64 | } 65 | 66 | module.exports = unzipN; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # lazit 2 | 3 | [![Build Status](https://travis-ci.org/zeusdeux/lazit.svg)](https://travis-ci.org/zeusdeux/lazit) 4 | 5 | Lazy, composable operations on iterators/generators for ES6 and beyond. 6 | 7 | > Use lazit right now with transpilers like [babeljs](http://babeljs.io) or the [Google Traceur Compiler](https://github.com/google/traceur-compiler) 8 | > or by using `build/lazit.js` or `build/lazit.min.js` which are precompiled using babeljs and browserified. 9 | 10 | Lazit lets you do stuff like: 11 | 12 | ```javascript 13 | let lazit = require('lazit'); 14 | let iterate = lazit.iterate; 15 | let take = lazit.take; 16 | let zip = lazit.zip; 17 | let map = lazit.map; 18 | let result; 19 | 20 | // use infinite lists without any worries since everything is lazy 21 | // here `iterate` is an infinite list builder function 22 | result = [...take(4, zip(iterate(x => x+1, 0), map(v => v*v, [1,2,3,4,5,6,7,8])))]; 23 | console.log(result); // [[0,1],[1,4],[2,9],[3,16]] 24 | 25 | // or stuff like 26 | 27 | let f = (a,b) => { b = b.slice(); b.unshift(a); return b; }; 28 | let g = (a,b) => { a = a.slice(); a.unshift(b); return a; }; 29 | 30 | console.log([...scanl(g, [], [1,2,3,4])]); // [[],[1],[2,1],[3,2,1],[4,3,2,1]] 31 | console.log(scanr(f, [], take(4, iterate(v => ++v, 1)))); // [[1,2,3,4],[2,3,4],[3,4],[4],[]] 32 | 33 | // or 34 | 35 | let map = lazit.map; 36 | let take = lazit.take; 37 | console.log([...take(3, map(v => { if (v === 0) throw Error('Divide by zero error'); else return 1/v; }, [1,2,3,0,5]))]); 38 | // output is [ 1, 0.5, 0.3333333333333333 ] 39 | // it doesn't blow up since the evaluation is lazy 40 | ``` 41 | 42 | Lazit exposes the same api whether you're dealing with infinite lists or finite lists. Also, the functions in lazit compose pretty much like they do in haskell, etc. 43 | 44 | Also, all functions that require more than one argument auto-curry in lazit. So you can do stuff like: 45 | 46 | ```javascript 47 | let lazit = require('lazit'); 48 | let mapIncFn = lazit.map(v => ++v); // pass only one out of the 2 args required by map 49 | 50 | console.log([...mapIncFn([1,2,3])]); // [2,3,4] 51 | ``` 52 | 53 | Current status: WIP 54 | -------------------------------------------------------------------------------- /src/es5/filter.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var filter = regeneratorRuntime.mark( 4 | 5 | // filter :: (a -> Bool) -> [a] -> [a] 6 | function filter(p, a) { 7 | var _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, x; 8 | 9 | return regeneratorRuntime.wrap(function filter$(context$1$0) { 10 | while (1) switch (context$1$0.prev = context$1$0.next) { 11 | case 0: 12 | _iteratorNormalCompletion = true; 13 | _didIteratorError = false; 14 | _iteratorError = undefined; 15 | context$1$0.prev = 3; 16 | _iterator = a[Symbol.iterator](); 17 | 18 | case 5: 19 | if (_iteratorNormalCompletion = (_step = _iterator.next()).done) { 20 | context$1$0.next = 13; 21 | break; 22 | } 23 | 24 | x = _step.value; 25 | 26 | if (!p(x)) { 27 | context$1$0.next = 10; 28 | break; 29 | } 30 | 31 | context$1$0.next = 10; 32 | return x; 33 | 34 | case 10: 35 | _iteratorNormalCompletion = true; 36 | context$1$0.next = 5; 37 | break; 38 | 39 | case 13: 40 | context$1$0.next = 19; 41 | break; 42 | 43 | case 15: 44 | context$1$0.prev = 15; 45 | context$1$0.t8 = context$1$0["catch"](3); 46 | _didIteratorError = true; 47 | _iteratorError = context$1$0.t8; 48 | 49 | case 19: 50 | context$1$0.prev = 19; 51 | context$1$0.prev = 20; 52 | 53 | if (!_iteratorNormalCompletion && _iterator["return"]) { 54 | _iterator["return"](); 55 | } 56 | 57 | case 22: 58 | context$1$0.prev = 22; 59 | 60 | if (!_didIteratorError) { 61 | context$1$0.next = 25; 62 | break; 63 | } 64 | 65 | throw _iteratorError; 66 | 67 | case 25: 68 | return context$1$0.finish(22); 69 | 70 | case 26: 71 | return context$1$0.finish(19); 72 | 73 | case 27: 74 | case "end": 75 | return context$1$0.stop(); 76 | } 77 | }, filter, this, [[3, 15, 19, 27], [20,, 22, 26]]); 78 | }); 79 | var cu = require("auto-curry"); 80 | 81 | module.exports = cu(filter); -------------------------------------------------------------------------------- /test/zipWith3.test.js: -------------------------------------------------------------------------------- 1 | require('should'); 2 | 3 | var map = require('../src/esnext/map'); 4 | var take = require('../src/esnext/take'); 5 | var repeat = require('../src/esnext/repeat'); 6 | var iterate = require('../src/esnext/iterate'); 7 | var zipWith3 = require('../src/esnext/zipWith3'); 8 | 9 | 10 | describe('lazit#zipWith3', function() { 11 | it('normal operation check', function() { 12 | var res; 13 | 14 | res = [...zipWith3((a,b,c) => a + b + c, [1,2,3], [5,6], [0,1])]; 15 | res.should.eql([6,9]); 16 | 17 | res = [...zipWith3((a,b,c) => a + b + c, repeat(1), [0,1,2,3], map(v => ++v, take(5, iterate(v => v*v, 2))))]; 18 | res.should.eql([4, 7, 20, 261]); 19 | 20 | res = [...zipWith3((a,b,c) => a + b + c, [2,4], ['a','b'], iterate(v => v + 1, 0))]; 21 | res.should.eql(['2a0', '4b1']); 22 | }); 23 | it('auto-curry check', function() { 24 | var res; 25 | var z = zipWith3((a,b,c) => a); 26 | var z2 = zipWith3((a,b,c) => a + b + c, ['a',1]); // auto-curry check 27 | var z3 = zipWith3((a,b,c) => a + b + c, [1], [2,3]); // auto-curry check 28 | 29 | res = [...z([1,2,3], take(5, repeat(1)), [0])]; 30 | res.should.eql([1]); 31 | 32 | res = [...z2([1],[0])]; 33 | res.should.eql(['a10']); 34 | 35 | res = [...z3([0])]; 36 | res.should.eql([3]); 37 | }); 38 | it('custom iterator check', function() { 39 | var res; 40 | var acc = ['c', 3]; 41 | 42 | function* customIterator(){ 43 | yield 'a'; 44 | yield 1; 45 | yield 'b'; 46 | yield 2; 47 | } 48 | 49 | res = [...zipWith3((a,b,c) => a + ' dude ' + b + ' what ' + c, customIterator(), acc, [20, 40])]; 50 | res.should.eql(['a dude c what 20', '1 dude 3 what 40']); 51 | acc.should.eql(['c', 3]); 52 | }); 53 | 54 | it('empty list check', function() { 55 | var res; 56 | var f = () => true; 57 | 58 | res = [...zipWith3(f, [1,2,3], [], [])]; 59 | res.should.eql([]); 60 | res = [...zipWith3(f, [], [], [])]; 61 | res.should.eql([]); 62 | res = [...zipWith3(f, [], [1,2,3], [])]; 63 | res.should.eql([]); 64 | res = [...zipWith3(f, [], [], [1,2,3])]; 65 | res.should.eql([]); 66 | }); 67 | }); 68 | -------------------------------------------------------------------------------- /src/es5/drop.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var drop = regeneratorRuntime.mark( 4 | 5 | // drop :: Int -> [a] -> [a] 6 | function drop(n, a) { 7 | var _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, x; 8 | 9 | return regeneratorRuntime.wrap(function drop$(context$1$0) { 10 | while (1) switch (context$1$0.prev = context$1$0.next) { 11 | case 0: 12 | _iteratorNormalCompletion = true; 13 | _didIteratorError = false; 14 | _iteratorError = undefined; 15 | context$1$0.prev = 3; 16 | _iterator = a[Symbol.iterator](); 17 | 18 | case 5: 19 | if (_iteratorNormalCompletion = (_step = _iterator.next()).done) { 20 | context$1$0.next = 17; 21 | break; 22 | } 23 | 24 | x = _step.value; 25 | 26 | if (!n) { 27 | context$1$0.next = 12; 28 | break; 29 | } 30 | 31 | --n; 32 | return context$1$0.abrupt("continue", 14); 33 | 34 | case 12: 35 | context$1$0.next = 14; 36 | return x; 37 | 38 | case 14: 39 | _iteratorNormalCompletion = true; 40 | context$1$0.next = 5; 41 | break; 42 | 43 | case 17: 44 | context$1$0.next = 23; 45 | break; 46 | 47 | case 19: 48 | context$1$0.prev = 19; 49 | context$1$0.t6 = context$1$0["catch"](3); 50 | _didIteratorError = true; 51 | _iteratorError = context$1$0.t6; 52 | 53 | case 23: 54 | context$1$0.prev = 23; 55 | context$1$0.prev = 24; 56 | 57 | if (!_iteratorNormalCompletion && _iterator["return"]) { 58 | _iterator["return"](); 59 | } 60 | 61 | case 26: 62 | context$1$0.prev = 26; 63 | 64 | if (!_didIteratorError) { 65 | context$1$0.next = 29; 66 | break; 67 | } 68 | 69 | throw _iteratorError; 70 | 71 | case 29: 72 | return context$1$0.finish(26); 73 | 74 | case 30: 75 | return context$1$0.finish(23); 76 | 77 | case 31: 78 | case "end": 79 | return context$1$0.stop(); 80 | } 81 | }, drop, this, [[3, 19, 23, 31], [24,, 26, 30]]); 82 | }); 83 | var cu = require("auto-curry"); 84 | 85 | module.exports = cu(drop); -------------------------------------------------------------------------------- /src/es5/takeWhile.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var takeWhile = regeneratorRuntime.mark( 4 | 5 | // takeWhile :: (a -> Bool) -> [a] -> [a] 6 | function takeWhile(p, a) { 7 | var _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, x; 8 | 9 | return regeneratorRuntime.wrap(function takeWhile$(context$1$0) { 10 | while (1) switch (context$1$0.prev = context$1$0.next) { 11 | case 0: 12 | _iteratorNormalCompletion = true; 13 | _didIteratorError = false; 14 | _iteratorError = undefined; 15 | context$1$0.prev = 3; 16 | _iterator = a[Symbol.iterator](); 17 | 18 | case 5: 19 | if (_iteratorNormalCompletion = (_step = _iterator.next()).done) { 20 | context$1$0.next = 16; 21 | break; 22 | } 23 | 24 | x = _step.value; 25 | 26 | if (!p(x)) { 27 | context$1$0.next = 12; 28 | break; 29 | } 30 | 31 | context$1$0.next = 10; 32 | return x; 33 | 34 | case 10: 35 | context$1$0.next = 13; 36 | break; 37 | 38 | case 12: 39 | return context$1$0.abrupt("break", 16); 40 | 41 | case 13: 42 | _iteratorNormalCompletion = true; 43 | context$1$0.next = 5; 44 | break; 45 | 46 | case 16: 47 | context$1$0.next = 22; 48 | break; 49 | 50 | case 18: 51 | context$1$0.prev = 18; 52 | context$1$0.t13 = context$1$0["catch"](3); 53 | _didIteratorError = true; 54 | _iteratorError = context$1$0.t13; 55 | 56 | case 22: 57 | context$1$0.prev = 22; 58 | context$1$0.prev = 23; 59 | 60 | if (!_iteratorNormalCompletion && _iterator["return"]) { 61 | _iterator["return"](); 62 | } 63 | 64 | case 25: 65 | context$1$0.prev = 25; 66 | 67 | if (!_didIteratorError) { 68 | context$1$0.next = 28; 69 | break; 70 | } 71 | 72 | throw _iteratorError; 73 | 74 | case 28: 75 | return context$1$0.finish(25); 76 | 77 | case 29: 78 | return context$1$0.finish(22); 79 | 80 | case 30: 81 | case "end": 82 | return context$1$0.stop(); 83 | } 84 | }, takeWhile, this, [[3, 18, 22, 30], [23,, 25, 29]]); 85 | }); 86 | var cu = require("auto-curry"); 87 | 88 | module.exports = cu(takeWhile); -------------------------------------------------------------------------------- /src/es5/dropWhile.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var dropWhile = regeneratorRuntime.mark( 4 | 5 | // dropWhile :: (a -> Bool) -> [a] -> [a] 6 | function dropWhile(p, a) { 7 | var doneDropping, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, x; 8 | 9 | return regeneratorRuntime.wrap(function dropWhile$(context$1$0) { 10 | while (1) switch (context$1$0.prev = context$1$0.next) { 11 | case 0: 12 | doneDropping = false; 13 | _iteratorNormalCompletion = true; 14 | _didIteratorError = false; 15 | _iteratorError = undefined; 16 | context$1$0.prev = 4; 17 | _iterator = a[Symbol.iterator](); 18 | 19 | case 6: 20 | if (_iteratorNormalCompletion = (_step = _iterator.next()).done) { 21 | context$1$0.next = 18; 22 | break; 23 | } 24 | 25 | x = _step.value; 26 | 27 | if (!(p(x) && !doneDropping)) { 28 | context$1$0.next = 12; 29 | break; 30 | } 31 | 32 | return context$1$0.abrupt("continue", 15); 33 | 34 | case 12: 35 | doneDropping = true; 36 | context$1$0.next = 15; 37 | return x; 38 | 39 | case 15: 40 | _iteratorNormalCompletion = true; 41 | context$1$0.next = 6; 42 | break; 43 | 44 | case 18: 45 | context$1$0.next = 24; 46 | break; 47 | 48 | case 20: 49 | context$1$0.prev = 20; 50 | context$1$0.t7 = context$1$0["catch"](4); 51 | _didIteratorError = true; 52 | _iteratorError = context$1$0.t7; 53 | 54 | case 24: 55 | context$1$0.prev = 24; 56 | context$1$0.prev = 25; 57 | 58 | if (!_iteratorNormalCompletion && _iterator["return"]) { 59 | _iterator["return"](); 60 | } 61 | 62 | case 27: 63 | context$1$0.prev = 27; 64 | 65 | if (!_didIteratorError) { 66 | context$1$0.next = 30; 67 | break; 68 | } 69 | 70 | throw _iteratorError; 71 | 72 | case 30: 73 | return context$1$0.finish(27); 74 | 75 | case 31: 76 | return context$1$0.finish(24); 77 | 78 | case 32: 79 | case "end": 80 | return context$1$0.stop(); 81 | } 82 | }, dropWhile, this, [[4, 20, 24, 32], [25,, 27, 31]]); 83 | }); 84 | var cu = require("auto-curry"); 85 | 86 | module.exports = cu(dropWhile); -------------------------------------------------------------------------------- /src/es5/scanl1.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var scanl1 = regeneratorRuntime.mark( 4 | 5 | // scanl1 :: (a -> a -> a) -> [a] -> [a] 6 | // scanl1 f [x1, x2, ...] == [x1, x1 `f` x2, ...] 7 | function scanl1(f, xs) { 8 | var prev, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, x; 9 | 10 | return regeneratorRuntime.wrap(function scanl1$(context$1$0) { 11 | while (1) switch (context$1$0.prev = context$1$0.next) { 12 | case 0: 13 | prev = null; 14 | _iteratorNormalCompletion = true; 15 | _didIteratorError = false; 16 | _iteratorError = undefined; 17 | context$1$0.prev = 4; 18 | _iterator = xs[Symbol.iterator](); 19 | 20 | case 6: 21 | if (_iteratorNormalCompletion = (_step = _iterator.next()).done) { 22 | context$1$0.next = 16; 23 | break; 24 | } 25 | 26 | x = _step.value; 27 | 28 | if (null !== prev) x = f(prev, x); 29 | context$1$0.next = 11; 30 | return x; 31 | 32 | case 11: 33 | x = isObject(x) ? clone(x) : x; 34 | prev = x; 35 | 36 | case 13: 37 | _iteratorNormalCompletion = true; 38 | context$1$0.next = 6; 39 | break; 40 | 41 | case 16: 42 | context$1$0.next = 22; 43 | break; 44 | 45 | case 18: 46 | context$1$0.prev = 18; 47 | context$1$0.t11 = context$1$0["catch"](4); 48 | _didIteratorError = true; 49 | _iteratorError = context$1$0.t11; 50 | 51 | case 22: 52 | context$1$0.prev = 22; 53 | context$1$0.prev = 23; 54 | 55 | if (!_iteratorNormalCompletion && _iterator["return"]) { 56 | _iterator["return"](); 57 | } 58 | 59 | case 25: 60 | context$1$0.prev = 25; 61 | 62 | if (!_didIteratorError) { 63 | context$1$0.next = 28; 64 | break; 65 | } 66 | 67 | throw _iteratorError; 68 | 69 | case 28: 70 | return context$1$0.finish(25); 71 | 72 | case 29: 73 | return context$1$0.finish(22); 74 | 75 | case 30: 76 | case "end": 77 | return context$1$0.stop(); 78 | } 79 | }, scanl1, this, [[4, 18, 22, 30], [23,, 25, 29]]); 80 | }); 81 | var clone = require("clone"); 82 | var cu = require("auto-curry"); 83 | var isObject = require("./util").isObject; 84 | 85 | module.exports = cu(scanl1); -------------------------------------------------------------------------------- /src/es5/scanl.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var scanl = regeneratorRuntime.mark( 4 | 5 | // scanl :: (b -> a -> b) -> b -> [a] -> [b] 6 | function scanl(f, acc, xs) { 7 | var _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, x; 8 | 9 | return regeneratorRuntime.wrap(function scanl$(context$1$0) { 10 | while (1) switch (context$1$0.prev = context$1$0.next) { 11 | case 0: 12 | acc = isObject(acc) ? clone(acc) : acc; 13 | _iteratorNormalCompletion = true; 14 | _didIteratorError = false; 15 | _iteratorError = undefined; 16 | context$1$0.prev = 4; 17 | _iterator = xs[Symbol.iterator](); 18 | 19 | case 6: 20 | if (_iteratorNormalCompletion = (_step = _iterator.next()).done) { 21 | context$1$0.next = 15; 22 | break; 23 | } 24 | 25 | x = _step.value; 26 | context$1$0.next = 10; 27 | return acc; 28 | 29 | case 10: 30 | acc = isObject(acc) ? clone(acc) : acc; 31 | acc = f(acc, x); 32 | 33 | case 12: 34 | _iteratorNormalCompletion = true; 35 | context$1$0.next = 6; 36 | break; 37 | 38 | case 15: 39 | context$1$0.next = 21; 40 | break; 41 | 42 | case 17: 43 | context$1$0.prev = 17; 44 | context$1$0.t10 = context$1$0["catch"](4); 45 | _didIteratorError = true; 46 | _iteratorError = context$1$0.t10; 47 | 48 | case 21: 49 | context$1$0.prev = 21; 50 | context$1$0.prev = 22; 51 | 52 | if (!_iteratorNormalCompletion && _iterator["return"]) { 53 | _iterator["return"](); 54 | } 55 | 56 | case 24: 57 | context$1$0.prev = 24; 58 | 59 | if (!_didIteratorError) { 60 | context$1$0.next = 27; 61 | break; 62 | } 63 | 64 | throw _iteratorError; 65 | 66 | case 27: 67 | return context$1$0.finish(24); 68 | 69 | case 28: 70 | return context$1$0.finish(21); 71 | 72 | case 29: 73 | context$1$0.next = 31; 74 | return acc; 75 | 76 | case 31: 77 | case "end": 78 | return context$1$0.stop(); 79 | } 80 | }, scanl, this, [[4, 17, 21, 29], [22,, 24, 28]]); 81 | }); 82 | var clone = require("clone"); 83 | var cu = require("auto-curry"); 84 | var isObject = require("./util").isObject; 85 | 86 | module.exports = cu(scanl); -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | /* jshint esnext:true */ 2 | 3 | // fn ops 4 | let flip = require('./esnext/flip'); 5 | 6 | // generic list ops pt 1 7 | let map = require('./esnext/map'); 8 | let concat = require('./esnext/concat'); 9 | let filter = require('./esnext/filter'); 10 | let head = require('./esnext/head'); 11 | let last = require('./esnext/last'); 12 | let tail = require('./esnext/tail'); 13 | let init = require('./esnext/init'); 14 | let reverse = require('./esnext/reverse'); 15 | 16 | // folds 17 | let foldl = require('./esnext/foldl'); 18 | let foldl1 = require('./esnext/foldl1'); 19 | let foldr = require('./esnext/foldr'); 20 | let foldr1 = require('./esnext/foldr1'); 21 | 22 | // scans 23 | let scanl = require('./esnext/scanl'); 24 | let scanl1 = require('./esnext/scanl1'); 25 | let scanr = require('./esnext/scanr'); 26 | // let scanr1 = require('./esnext/scanr1'); 27 | 28 | // infinite lists 29 | let iterate = require('./esnext/iterate'); 30 | let repeat = require('./esnext/repeat'); 31 | let replicate = require('./esnext/replicate'); 32 | let cycle = require('./esnext/cycle'); 33 | 34 | // generic list ops pt 2 35 | let take = require('./esnext/take'); 36 | let drop = require('./esnext/drop'); 37 | let splitAt = require('./esnext/splitAt'); 38 | let takeWhile = require('./esnext/takeWhile'); 39 | let dropWhile = require('./esnext/dropWhile'); 40 | let span = require('./esnext/span'); 41 | let spanInv = require('./esnext/spanInv'); 42 | 43 | // zips 44 | let zip = require('./esnext/zip'); 45 | let zip3 = require('./esnext/zip3'); 46 | let zipN = require('./esnext/zipN'); 47 | let zipWith = require('./esnext/zipWith'); 48 | let zipWith3 = require('./esnext/zipWith3'); 49 | let zipWithN = require('./esnext/zipWithN'); 50 | 51 | // unzips 52 | let unzip = require('./esnext/unzip'); 53 | let unzipN = require('./esnext/unzipN'); 54 | let unzip3 = require('./esnext/unzip3'); 55 | 56 | module.exports = { 57 | flip: flip, 58 | map: map, 59 | concat: concat, 60 | filter: filter, 61 | head: head, 62 | last: last, 63 | tail: tail, 64 | init: init, 65 | reverse: reverse, 66 | foldl: foldl, 67 | foldl1: foldl1, 68 | foldr: foldr, 69 | foldr1: foldr1, 70 | scanl: scanl, 71 | scanl1: scanl1, 72 | scanr: scanr, 73 | // scanr1: scanr1, 74 | take: take, 75 | drop: drop, 76 | splitAt: splitAt, 77 | takeWhile: takeWhile, 78 | dropWhile: dropWhile, 79 | span: span, 80 | spanInv: spanInv, 81 | zip: zip, 82 | zip3: zip3, 83 | zipWith: zipWith, 84 | zipWith3: zipWith3, 85 | zipN: zipN, 86 | zipWithN: zipWithN, 87 | unzip: unzip, 88 | unzip3: unzip3, 89 | unzipN: unzipN, 90 | iterate: iterate, 91 | repeat: repeat, 92 | replicate: replicate, 93 | cycle: cycle 94 | }; 95 | -------------------------------------------------------------------------------- /src/es5/take.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var take = regeneratorRuntime.mark( 4 | 5 | // take :: Int -> [a] -> [a] 6 | function take(n, a) { 7 | var _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, x; 8 | 9 | return regeneratorRuntime.wrap(function take$(context$1$0) { 10 | while (1) switch (context$1$0.prev = context$1$0.next) { 11 | case 0: 12 | _iteratorNormalCompletion = true; 13 | _didIteratorError = false; 14 | _iteratorError = undefined; 15 | context$1$0.prev = 3; 16 | _iterator = a[Symbol.iterator](); 17 | 18 | case 5: 19 | if (_iteratorNormalCompletion = (_step = _iterator.next()).done) { 20 | context$1$0.next = 23; 21 | break; 22 | } 23 | 24 | x = _step.value; 25 | 26 | if (!(n > 1)) { 27 | context$1$0.next = 13; 28 | break; 29 | } 30 | 31 | context$1$0.next = 10; 32 | return x; 33 | 34 | case 10: 35 | n--; 36 | context$1$0.next = 20; 37 | break; 38 | 39 | case 13: 40 | if (!(n === 1)) { 41 | context$1$0.next = 19; 42 | break; 43 | } 44 | 45 | context$1$0.next = 16; 46 | return x; 47 | 48 | case 16: 49 | return context$1$0.abrupt("break", 23); 50 | 51 | case 19: 52 | return context$1$0.abrupt("break", 23); 53 | 54 | case 20: 55 | _iteratorNormalCompletion = true; 56 | context$1$0.next = 5; 57 | break; 58 | 59 | case 23: 60 | context$1$0.next = 29; 61 | break; 62 | 63 | case 25: 64 | context$1$0.prev = 25; 65 | context$1$0.t12 = context$1$0["catch"](3); 66 | _didIteratorError = true; 67 | _iteratorError = context$1$0.t12; 68 | 69 | case 29: 70 | context$1$0.prev = 29; 71 | context$1$0.prev = 30; 72 | 73 | if (!_iteratorNormalCompletion && _iterator["return"]) { 74 | _iterator["return"](); 75 | } 76 | 77 | case 32: 78 | context$1$0.prev = 32; 79 | 80 | if (!_didIteratorError) { 81 | context$1$0.next = 35; 82 | break; 83 | } 84 | 85 | throw _iteratorError; 86 | 87 | case 35: 88 | return context$1$0.finish(32); 89 | 90 | case 36: 91 | return context$1$0.finish(29); 92 | 93 | case 37: 94 | case "end": 95 | return context$1$0.stop(); 96 | } 97 | }, take, this, [[3, 25, 29, 37], [30,, 32, 36]]); 98 | }); 99 | var cu = require("auto-curry"); 100 | 101 | module.exports = cu(take); 102 | 103 | // this condition makes sure that we yield only 104 | // exactly n times and not n + 1 times which 105 | // would happen if we were using the old if (n--) code -------------------------------------------------------------------------------- /src/es5/concat.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var concat = regeneratorRuntime.mark( 4 | 5 | // concat :: [a] -> [a] -> [a] 6 | // Append two lists 7 | // If the first list is not finite, the result is the first list. 8 | function concat(a, b) { 9 | var _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, x, _iteratorNormalCompletion2, _didIteratorError2, _iteratorError2, _iterator2, _step2; 10 | 11 | return regeneratorRuntime.wrap(function concat$(context$1$0) { 12 | while (1) switch (context$1$0.prev = context$1$0.next) { 13 | case 0: 14 | _iteratorNormalCompletion = true; 15 | _didIteratorError = false; 16 | _iteratorError = undefined; 17 | context$1$0.prev = 3; 18 | _iterator = a[Symbol.iterator](); 19 | 20 | case 5: 21 | if (_iteratorNormalCompletion = (_step = _iterator.next()).done) { 22 | context$1$0.next = 12; 23 | break; 24 | } 25 | 26 | x = _step.value; 27 | context$1$0.next = 9; 28 | return x; 29 | 30 | case 9: 31 | _iteratorNormalCompletion = true; 32 | context$1$0.next = 5; 33 | break; 34 | 35 | case 12: 36 | context$1$0.next = 18; 37 | break; 38 | 39 | case 14: 40 | context$1$0.prev = 14; 41 | context$1$0.t0 = context$1$0["catch"](3); 42 | _didIteratorError = true; 43 | _iteratorError = context$1$0.t0; 44 | 45 | case 18: 46 | context$1$0.prev = 18; 47 | context$1$0.prev = 19; 48 | 49 | if (!_iteratorNormalCompletion && _iterator["return"]) { 50 | _iterator["return"](); 51 | } 52 | 53 | case 21: 54 | context$1$0.prev = 21; 55 | 56 | if (!_didIteratorError) { 57 | context$1$0.next = 24; 58 | break; 59 | } 60 | 61 | throw _iteratorError; 62 | 63 | case 24: 64 | return context$1$0.finish(21); 65 | 66 | case 25: 67 | return context$1$0.finish(18); 68 | 69 | case 26: 70 | _iteratorNormalCompletion2 = true; 71 | _didIteratorError2 = false; 72 | _iteratorError2 = undefined; 73 | context$1$0.prev = 29; 74 | _iterator2 = b[Symbol.iterator](); 75 | 76 | case 31: 77 | if (_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done) { 78 | context$1$0.next = 38; 79 | break; 80 | } 81 | 82 | x = _step2.value; 83 | context$1$0.next = 35; 84 | return x; 85 | 86 | case 35: 87 | _iteratorNormalCompletion2 = true; 88 | context$1$0.next = 31; 89 | break; 90 | 91 | case 38: 92 | context$1$0.next = 44; 93 | break; 94 | 95 | case 40: 96 | context$1$0.prev = 40; 97 | context$1$0.t1 = context$1$0["catch"](29); 98 | _didIteratorError2 = true; 99 | _iteratorError2 = context$1$0.t1; 100 | 101 | case 44: 102 | context$1$0.prev = 44; 103 | context$1$0.prev = 45; 104 | 105 | if (!_iteratorNormalCompletion2 && _iterator2["return"]) { 106 | _iterator2["return"](); 107 | } 108 | 109 | case 47: 110 | context$1$0.prev = 47; 111 | 112 | if (!_didIteratorError2) { 113 | context$1$0.next = 50; 114 | break; 115 | } 116 | 117 | throw _iteratorError2; 118 | 119 | case 50: 120 | return context$1$0.finish(47); 121 | 122 | case 51: 123 | return context$1$0.finish(44); 124 | 125 | case 52: 126 | case "end": 127 | return context$1$0.stop(); 128 | } 129 | }, concat, this, [[3, 14, 18, 26], [19,, 21, 25], [29, 40, 44, 52], [45,, 47, 51]]); 130 | }); 131 | var cu = require("auto-curry"); 132 | 133 | module.exports = cu(concat); -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "env": { 4 | "node": true, 5 | "mocha": true, 6 | "browser": true, 7 | "builtin": true, 8 | "es6": true 9 | }, 10 | "ecmaFeatures": { 11 | "arrowFunctions": true, 12 | "binaryLiterals": true, 13 | "blockBindings": true, 14 | "classes": true, 15 | "defaultParams": true, 16 | "destructuring": true, 17 | "forOf": true, 18 | "generators": true, 19 | "modules": true, 20 | "objectLiteralComputedProperties": true, 21 | "objectLiteralDuplicateProperties": true, 22 | "objectLiteralShorthandMethods": true, 23 | "objectLiteralShorthandProperties": true, 24 | "octalLiterals": true, 25 | "regexUFlag": true, 26 | "regexYFlag": true, 27 | "spread": true, 28 | "superInFunctions": true, 29 | "templateStrings": true, 30 | "unicodeCodePointEscapes": true, 31 | "globalReturn": true, 32 | "jsx": true 33 | }, 34 | "rules": { 35 | "comma-dangle": 0, 36 | "no-cond-assign": [ 37 | 2, 38 | "except-parens" 39 | ], 40 | "no-underscore-dangle": 0, 41 | "no-console": 2, 42 | "no-constant-condition": 1, 43 | "no-debugger": 2, 44 | "no-dupe-args": 2, 45 | "no-dupe-keys": 2, 46 | "no-duplicate-case": 2, 47 | "no-empty": 2, 48 | "no-empty-class": 2, 49 | "no-ex-assign": 2, 50 | "no-extra-boolean-cast": 1, 51 | "no-multi-spaces": 0, 52 | "no-extra-semi": 2, 53 | "no-func-assign": 2, 54 | "no-inner-declarations": 2, 55 | "no-invalid-regexp": 2, 56 | "no-negated-in-lhs": 2, 57 | "no-obj-calls": 2, 58 | "no-regex-spaces": 2, 59 | "no-sparse-arrays": 2, 60 | "no-unreachable": 2, 61 | "use-isnan": 2, 62 | "valid-typeof": 2, 63 | "block-scoped-var": 2, 64 | "consistent-return": 1, 65 | "curly": [1, "multi"], 66 | "dot-notation": 2, 67 | "eqeqeq": 2, 68 | "guard-for-in": 2, 69 | "no-alert": 2, 70 | "no-caller": 2, 71 | "no-div-regex": 2, 72 | "no-else-return": 2, 73 | "no-eq-null": 2, 74 | "no-eval": 2, 75 | "no-extend-native": 2, 76 | "no-extra-bind": 2, 77 | "no-fallthrough": 1, 78 | "no-floating-decimal": 2, 79 | "no-implied-eval": 2, 80 | "no-labels": 2, 81 | "no-lone-blocks": 2, 82 | "no-loop-func": 2, 83 | "no-multi-spaces": [2, { exceptions: { "AssignmentExpression": true, "VariableDeclarator": true } }], 84 | "no-multi-str": 2, 85 | "no-native-reassign": 2, 86 | "no-new": 1, 87 | "no-new-func": 2, 88 | "no-new-wrappers": 2, 89 | "no-octal": 1, 90 | "no-octal-escape": 2, 91 | "no-param-reassign": 0, 92 | "no-redeclare": 2, 93 | "no-return-assign": 2, 94 | "no-script-url": 2, 95 | "no-self-compare": 2, 96 | "no-throw-literal": 2, 97 | "no-unused-expressions": 2, 98 | "no-with": 2, 99 | "radix": 2, 100 | "strict": [2, "global"], 101 | "yoda": 0, 102 | "no-delete-var": 2, 103 | "no-shadow": 1, 104 | "no-shadow-restricted-names": 2, 105 | "no-undef": 2, 106 | "no-undef-init": 2, 107 | "no-undefined": 2, 108 | "no-unused-vars": 2, 109 | "no-use-before-define": 1, 110 | "indent": [2, 2], 111 | "camelcase": 2, 112 | "comma-spacing": [2, {"before": false, "after": true}], 113 | "consistent-this": [0, "self"], 114 | "eol-last": 2, 115 | "key-spacing": [2, {"beforeColon": false, "afterColon": true}], 116 | "new-cap": 2, 117 | "newline-after-var": [1, "always"], 118 | "no-lonely-if": 2, 119 | "no-mixed-spaces-and-tabs": 2, 120 | "no-new-object": 2, 121 | "no-spaced-func": 2, 122 | "no-trailing-spaces": 2, 123 | "no-wrap-func": 2, 124 | "quote-props": [2, "as-needed"], 125 | "quotes": [1, "single", "avoid-escape"], 126 | "space-before-blocks": [2, "always"], 127 | "space-infix-ops": 2, 128 | "space-return-throw-case": 2, 129 | "space-unary-ops": 2, 130 | "spaced-line-comment": 1, 131 | //es6 specific 132 | "no-var": 2, 133 | "generator-star-spacing": [2, "after"] 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/es5/cycle.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var cycle = regeneratorRuntime.mark( 4 | 5 | // cycle :: [a] -> [a] 6 | function cycle(a) { 7 | var yieldIt = regeneratorRuntime.mark(function yieldIt(x) { 8 | return regeneratorRuntime.wrap(function yieldIt$(context$2$0) { 9 | while (1) switch (context$2$0.prev = context$2$0.next) { 10 | case 0: 11 | if (isObject(x)) { 12 | context$2$0.next = 5; 13 | break; 14 | } 15 | 16 | context$2$0.next = 3; 17 | return x; 18 | 19 | case 3: 20 | context$2$0.next = 7; 21 | break; 22 | 23 | case 5: 24 | context$2$0.next = 7; 25 | return clone(x); 26 | 27 | case 7: 28 | case "end": 29 | return context$2$0.stop(); 30 | } 31 | }, yieldIt, this); 32 | }); 33 | 34 | var isGenFnFlag, tempIt, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, x, _iteratorNormalCompletion2, _didIteratorError2, _iteratorError2, _iterator2, _step2; 35 | 36 | return regeneratorRuntime.wrap(function cycle$(context$1$0) { 37 | while (1) switch (context$1$0.prev = context$1$0.next) { 38 | case 0: 39 | isGenFnFlag = isGenFn(a); 40 | tempIt = isGenFnFlag ? a()[Symbol.iterator]() : a[Symbol.iterator](); 41 | 42 | if (!tempIt.next().done) { 43 | context$1$0.next = 4; 44 | break; 45 | } 46 | 47 | throw new Error("Cannot cycle empty list/iterable"); 48 | 49 | case 4: 50 | if (!true) { 51 | context$1$0.next = 60; 52 | break; 53 | } 54 | 55 | if (isGenFnFlag) { 56 | context$1$0.next = 33; 57 | break; 58 | } 59 | 60 | _iteratorNormalCompletion = true; 61 | _didIteratorError = false; 62 | _iteratorError = undefined; 63 | context$1$0.prev = 9; 64 | _iterator = a[Symbol.iterator](); 65 | 66 | case 11: 67 | if (_iteratorNormalCompletion = (_step = _iterator.next()).done) { 68 | context$1$0.next = 17; 69 | break; 70 | } 71 | 72 | x = _step.value; 73 | return context$1$0.delegateYield(yieldIt(x), "t2", 14); 74 | 75 | case 14: 76 | _iteratorNormalCompletion = true; 77 | context$1$0.next = 11; 78 | break; 79 | 80 | case 17: 81 | context$1$0.next = 23; 82 | break; 83 | 84 | case 19: 85 | context$1$0.prev = 19; 86 | context$1$0.t3 = context$1$0["catch"](9); 87 | _didIteratorError = true; 88 | _iteratorError = context$1$0.t3; 89 | 90 | case 23: 91 | context$1$0.prev = 23; 92 | context$1$0.prev = 24; 93 | 94 | if (!_iteratorNormalCompletion && _iterator["return"]) { 95 | _iterator["return"](); 96 | } 97 | 98 | case 26: 99 | context$1$0.prev = 26; 100 | 101 | if (!_didIteratorError) { 102 | context$1$0.next = 29; 103 | break; 104 | } 105 | 106 | throw _iteratorError; 107 | 108 | case 29: 109 | return context$1$0.finish(26); 110 | 111 | case 30: 112 | return context$1$0.finish(23); 113 | 114 | case 31: 115 | context$1$0.next = 58; 116 | break; 117 | 118 | case 33: 119 | _iteratorNormalCompletion2 = true; 120 | _didIteratorError2 = false; 121 | _iteratorError2 = undefined; 122 | context$1$0.prev = 36; 123 | _iterator2 = a()[Symbol.iterator](); 124 | 125 | case 38: 126 | if (_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done) { 127 | context$1$0.next = 44; 128 | break; 129 | } 130 | 131 | x = _step2.value; 132 | return context$1$0.delegateYield(yieldIt(x), "t4", 41); 133 | 134 | case 41: 135 | _iteratorNormalCompletion2 = true; 136 | context$1$0.next = 38; 137 | break; 138 | 139 | case 44: 140 | context$1$0.next = 50; 141 | break; 142 | 143 | case 46: 144 | context$1$0.prev = 46; 145 | context$1$0.t5 = context$1$0["catch"](36); 146 | _didIteratorError2 = true; 147 | _iteratorError2 = context$1$0.t5; 148 | 149 | case 50: 150 | context$1$0.prev = 50; 151 | context$1$0.prev = 51; 152 | 153 | if (!_iteratorNormalCompletion2 && _iterator2["return"]) { 154 | _iterator2["return"](); 155 | } 156 | 157 | case 53: 158 | context$1$0.prev = 53; 159 | 160 | if (!_didIteratorError2) { 161 | context$1$0.next = 56; 162 | break; 163 | } 164 | 165 | throw _iteratorError2; 166 | 167 | case 56: 168 | return context$1$0.finish(53); 169 | 170 | case 57: 171 | return context$1$0.finish(50); 172 | 173 | case 58: 174 | context$1$0.next = 4; 175 | break; 176 | 177 | case 60: 178 | case "end": 179 | return context$1$0.stop(); 180 | } 181 | }, cycle, this, [[9, 19, 23, 31], [24,, 26, 30], [36, 46, 50, 58], [51,, 53, 57]]); 182 | }); 183 | var clone = require("clone"); 184 | var isObject = require("./util").isObject; 185 | var isGenFn = require("is-generator").fn; 186 | 187 | module.exports = cycle; 188 | 189 | // See the comment in repeat --------------------------------------------------------------------------------