Infinite lists!
The goal of this library is to let you create potentially infinite lists in a memory efficient way.
It's based on javascript's Generators, and it provides many different generation methods and modifiers.
API
The API provides three different kind of methods: Generators, Executions and Modifiers
Generators
Generators are the entry point for this library. They let you create lists in many different ways:
Infinits.range
Lets you create a list from a range of numbers.
; // [0, 1, 2, ...]; // [1, 2, 3, ...]; // [0, ..., 9]; // [0, -1, -2, -3, ...];
As you see, range accepts this options (with their corresponding default)
;
Infinits.tabulate
Lets you create a list from a function taking the item's index.
; // [1, 2, 3, ...]; // [-1, -2, -3, ...]; // [1, 2, 4, 8, 16, ...]; // [0, ..., 9]; // ['right', 'left', 'right', 'left', ...];
It takes a function of type
;
and optionally a number to limit the elements count (Infinity by default).
Infinits.repeat
Lets you crate a list by repeating a value
; // [0, 0, 0, 0, ...]; // ['messi', 'messi', 'messi', ...]; // [42, 42, 42, 42, 42];
It takes a value of any type and optionally a number to limit the elements count (Infinity by default).
Infinits.from
Lets you crate a list from any javascript Iterable (array, string, etc...).
; // [42, 42, 42, 42, 42]; // ["i", "n", "f", "i", "n", "i", "t", "s"];
Executions
Executions are ways of consuming a list. This might never end if a list is actually infinite, so be careful what you do!
exec
Returns an Iterable from a List
; ; for of five42.exec
forEach
Runs a callback on each element of the array (index is also available).
; Infinits.from.forEach; // Also accepts an indexInfinits.repeat0, 10.forEach;
toArray
Returns a good old array.
; // [0, 0, 0, 0, 0];
reduce
Basically the same as javascript's reduce.
; // 0 + 1 + 2 + 3 + 4 = 10; // -1 / 12. LOL, YOU WISH! This never ends :(;
count
Returns the number of elements in a list.
Optionally takes a predicate to determine which elements to count
; // 5; // 5;
nth
Returns the nth element of the list.
Keep in mind this process is O(N)! We have to traverse the list to get to the nth element.
; // 0; // 100;
every
Returns true if a predicate is true for all elements in the list.
; // true; // false;
some
Returns true if a predicate is true for at least one element in the list
; // true; // false;
find
Returns the first element that makes a predicate true, undefined if no element makes it.
; // 1001; // undefined;
findIndex
Returns the index of the first element that makes a predicate true, -1 if no element makes it.
; // 1001; // -1;
Modifiers
Modifiers provide a way of transforming lists in a lazy way.
All modifiers are chainable.
until
remove all elements after the first one to make a predicate true.
; // [0, ..., 1000];
take
Limit a list to a specific length.
; // [0, ..., 99];
drop
Remove the first N elements from a list.
; // [50, ..., 99];
map
Basically the same as javascript's map.
; // [0, 2, 4, 6, 8, 10]; // [0, ..., 9];
filter
Basically the same as javascript's filter.
; // [0, 2, 4, 6, ...];
Infinits.zipLong
(static)
Takes any number of lists and returns a list of tuples. Nth element in the new list is a tuple made from the Nth element of each list.
The resulting list's length will be that of the longest list. undefined
will be used to fill the holes.
; ;; // [ [0, 1], [2, 3], [4, 5], ... ]; ;; // [ [0, 0], [1, 1], [2, 2], [3, undefined], [4, undefined] ]; ;;; // [ [0, 0, 0], [2, 3, 5], [4, 6, 10], [6, 9, 15], ...];
Infinits.zipShort
(static)
same as zipLong but the resulting list's length will be that of the shortest list. Won't produce any holes.
; ;; // [ [0, 1], [2, 3], [4, 5], ... ] Same as zipLong!; ;; // [ [0, 0], [1, 1], [2, 2] ]; ;;; // [ [0, 0, 0], [2, 3, 5], [4, 6, 10], [6, 9, 15], ...];
Infinits.unzip
(static)
Takes a list of tuples and returns many lists. Basically the opposite of zipLong.
; ;; // [ [0, 1], [2, 3], [4, 5], ... ]; // evensAgain == evens, oddsAgain == odds;
flatten
Similar to javascript's flat, but only depth 1.
If the list isn't a list of lists, it does nothing.
// [[0, 1], [0, 1], [0, 1], ...]; // [0, 1, 0, 1, 0, 1, ...]; // [0, 1, 0, 1, 0, 1, ...];
deepFlatten
Similar to javascript's flat, but Infinite depth.
Type inference only works until the 10th level cause Typescript doesn't support recursive types :(.
// [[0, 1], [0, 1]]; // [[[0, 1], [0, 1]], [[0, 1], [0, 1]]]; // [[[[0, 1], [0, 1]], [[0, 1], [0, 1]]], [[[0, 1], [0, 1]], [[0, 1], [0, 1]]]]; // [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; // ... After nesting more and more lists, more than 10 times ...; // You'll have to use `as Infinits<YourBaseType>`;
append
appends a list to another one. Similar to javascript's concat
; ;; // [0, 0, 0, 0, 0, 1, 1, 1, 1, 1];
enumerate
Returns a list of pairs, first element of the pair is the original element, second is the index in the list.
; // [ [0, 0], [0, 1], [0, 2], ...]; // Equivalent to; // And to;
scan
Similar to reduce, but returns a list of every partial result and works lazily.
; // All partial sums of [0, 1, 2, ...]// [0, 1, 3, 6, 10, 15, 21, 28, ...];
inspect
Lazily runs a callback on every item. This means the callback will be executed once the value is consumed.
; // Does nothing, yet... .inspectconsole.log`inspected ` .mapx * 2; // This logs a lot!inspected.forEachconsole.log`then logged `; /* * LOGS: * inspected 0 * then logged 0 * inspected 1 * then logged 2 * inspected 2 * then logged 4 */
loop
Takes a list and make it circular. This means: when the list ends, start again from the begining.
; // [0, 1, 0, 1, 0, 1, ...];
splitBy
Takes a function that returns a key (string) for each element, returns an object that groups elements into multiple lists for each of those keys.
If you take a list from a non-existing key (a key that your function will never return) you won't get any errors, but executions of that list will run forever and not produce a single value :(. This happens cause you can't know in advance all possible keys produced by an infinite list, so we can't assume anything.
; // [0, 1, 2, 3, ...]; ; // [0, 2, 4, 6, 8]; // [1, 3, 5, 7, 9];
TODO:
Improve test coverage, please :(