diff --git a/src/main.js b/src/main.js index 0c6f2d1..f24727f 100644 --- a/src/main.js +++ b/src/main.js @@ -8,8 +8,10 @@ const fastCartesian = function(...iterables) { iterables.forEach(validateIterable) + const arrays = iterables.map(arrify) + const result = [] - iterate(iterables, result, [], 0) + iterate(arrays, result, [], 0) return result } @@ -23,19 +25,28 @@ const validateIterable = function(iterable) { } } +// Some iterables are stateful, e.g. generators. We need to iterate them first. +const arrify = function(iterable) { + if (Array.isArray(iterable)) { + return iterable + } + + return [...iterable] +} + // We use imperative code as it faster than functional code because it does not // create extra arrays. We try re-use and mutate arrays as much as possible. // We need to make sure callers parameters are not mutated though. /* eslint-disable max-params, fp/no-loops, fp/no-mutating-methods */ -const iterate = function(iterables, result, values, index) { - if (index === iterables.length) { +const iterate = function(arrays, result, values, index) { + if (index === arrays.length) { result.push(values.slice()) return } - for (const value of iterables[index]) { + for (const value of arrays[index]) { values.push(value) - iterate(iterables, result, values, index + 1) + iterate(arrays, result, values, index + 1) values.pop() } } diff --git a/test/main.js b/test/main.js index 2b6d60d..edf3eaa 100644 --- a/test/main.js +++ b/test/main.js @@ -32,6 +32,7 @@ const generator = function*() { [new Map([[{}, 0], [{}, 1]])], [new Set([0, 1])], [generator()], + [[0, 1], generator()], ].forEach(args => { const title = prettyFormat(args, { min: true }) test(title, t => { diff --git a/test/snapshots/main.js.md b/test/snapshots/main.js.md index 42da365..c03a706 100644 --- a/test/snapshots/main.js.md +++ b/test/snapshots/main.js.md @@ -231,3 +231,26 @@ Generated by [AVA](https://ava.li). 1, ], ] + +## [[0, 1], {}] + +> Snapshot 1 + + [ + [ + 0, + 0, + ], + [ + 0, + 1, + ], + [ + 1, + 0, + ], + [ + 1, + 1, + ], + ] diff --git a/test/snapshots/main.js.snap b/test/snapshots/main.js.snap index 6f3a299..2e3cfc5 100644 Binary files a/test/snapshots/main.js.snap and b/test/snapshots/main.js.snap differ