UNPKG

list

Version:

Fast purely functional immutable lists.

1,568 lines 53.8 kB
"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); Object.defineProperty(exports, "__esModule", { value: true }); var branchingFactor = 32; var branchBits = 5; var mask = 31; function isSetoid(a) { return a && typeof a["fantasy-land/equals"] === "function"; } function elementEquals(a, b) { if (a === b) { return true; } else if (isSetoid(a)) { return a["fantasy-land/equals"](b); } else { return false; } } function createPath(depth, value) { var current = value; for (var i = 0; i < depth; ++i) { current = new Node(undefined, [current]); } return current; } function copyArray(source) { var array = []; for (var i = 0; i < source.length; ++i) { array[i] = source[i]; } return array; } function pushElements(source, target, offset, amount) { for (var i = offset; i < offset + amount; ++i) { target.push(source[i]); } } function copyIndices(source, sourceStart, target, targetStart, length) { for (var i = 0; i < length; ++i) { target[targetStart + i] = source[sourceStart + i]; } } function arrayPrepend(value, array) { var newLength = array.length + 1; var result = new Array(newLength); result[0] = value; for (var i = 1; i < newLength; ++i) { result[i] = array[i - 1]; } return result; } function reverseArray(array) { return array.slice().reverse(); } function arrayFirst(array) { return array[0]; } function arrayLast(array) { return array[array.length - 1]; } var pathResult = { path: 0, index: 0, updatedOffset: 0 }; function getPath(index, offset, depth, sizes) { if (sizes === undefined && offset !== 0) { pathResult.updatedOffset = 0; index = handleOffset(depth, offset, index); } var path = (index >> (depth * branchBits)) & mask; if (sizes !== undefined) { while (sizes[path] <= index) { path++; } var traversed = path === 0 ? 0 : sizes[path - 1]; index -= traversed; pathResult.updatedOffset = offset; } pathResult.path = path; pathResult.index = index; return pathResult; } function updateNode(node, depth, index, offset, value) { var _a = getPath(index, offset, depth, node.sizes), path = _a.path, newIndex = _a.index, updatedOffset = _a.updatedOffset; var array = copyArray(node.array); array[path] = depth > 0 ? updateNode(array[path], depth - 1, newIndex, updatedOffset, value) : value; return new Node(node.sizes, array); } var Node = (function () { function Node(sizes, array) { this.sizes = sizes; this.array = array; } return Node; }()); exports.Node = Node; function cloneNode(_a) { var sizes = _a.sizes, array = _a.array; return new Node(sizes === undefined ? undefined : copyArray(sizes), copyArray(array)); } var emptyAffix = [0]; var affixBits = 6; var affixMask = 63; function getSuffixSize(l) { return l.bits & affixMask; } function getPrefixSize(l) { return (l.bits >> affixBits) & affixMask; } function getDepth(l) { return l.bits >> (affixBits * 2); } function setPrefix(size, bits) { return (size << affixBits) | (bits & ~(affixMask << affixBits)); } function setSuffix(size, bits) { return size | (bits & ~affixMask); } function setDepth(depth, bits) { return ((depth << (affixBits * 2)) | (bits & (affixMask | (affixMask << affixBits)))); } function incrementPrefix(bits) { return bits + (1 << affixBits); } function incrementSuffix(bits) { return bits + 1; } function incrementDepth(bits) { return bits + (1 << (affixBits * 2)); } function decrementDepth(bits) { return bits - (1 << (affixBits * 2)); } var List = (function () { function List(bits, offset, length, prefix, root, suffix) { this.bits = bits; this.offset = offset; this.length = length; this.prefix = prefix; this.root = root; this.suffix = suffix; } List.prototype[Symbol.iterator] = function () { return new ForwardListIterator(this); }; List.prototype.toJSON = function () { return toArray(this); }; return List; }()); exports.List = List; function cloneList(l) { return new List(l.bits, l.offset, l.length, l.prefix, l.root, l.suffix); } var ListIterator = (function () { function ListIterator(l, direction) { this.l = l; this.result = { done: false, value: undefined }; this.idx = direction === 1 ? -1 : l.length; this.prefixSize = getPrefixSize(l); this.middleSize = l.length - getSuffixSize(l); if (l.root !== undefined) { var depth = getDepth(l); this.stack = new Array(depth + 1); this.indices = new Array(depth + 1); var currentNode = l.root.array; for (var i = depth; 0 <= i; --i) { this.stack[i] = currentNode; var idx = direction === 1 ? 0 : currentNode.length - 1; this.indices[i] = idx; currentNode = currentNode[idx].array; } this.indices[0] -= direction; } } return ListIterator; }()); var ForwardListIterator = (function (_super) { __extends(ForwardListIterator, _super); function ForwardListIterator(l) { return _super.call(this, l, 1) || this; } ForwardListIterator.prototype.nextInTree = function () { for (var i = 0; ++this.indices[i] === this.stack[i].length; ++i) { this.indices[i] = 0; } for (; 0 < i; --i) { this.stack[i - 1] = this.stack[i][this.indices[i]].array; } }; ForwardListIterator.prototype.next = function () { var newVal; var idx = ++this.idx; if (idx < this.prefixSize) { newVal = this.l.prefix[this.prefixSize - idx - 1]; } else if (idx < this.middleSize) { this.nextInTree(); newVal = this.stack[0][this.indices[0]]; } else if (idx < this.l.length) { newVal = this.l.suffix[idx - this.middleSize]; } else { this.result.done = true; } this.result.value = newVal; return this.result; }; return ForwardListIterator; }(ListIterator)); var BackwardsListIterator = (function (_super) { __extends(BackwardsListIterator, _super); function BackwardsListIterator(l) { return _super.call(this, l, -1) || this; } BackwardsListIterator.prototype.prevInTree = function () { for (var i = 0; this.indices[i] === 0; ++i) { } --this.indices[i]; for (; 0 < i; --i) { var n = this.stack[i][this.indices[i]].array; this.stack[i - 1] = n; this.indices[i - 1] = n.length - 1; } }; BackwardsListIterator.prototype.next = function () { var newVal; var idx = --this.idx; if (this.middleSize <= idx) { newVal = this.l.suffix[idx - this.middleSize]; } else if (this.prefixSize <= idx) { this.prevInTree(); newVal = this.stack[0][this.indices[0]]; } else if (0 <= idx) { newVal = this.l.prefix[this.prefixSize - idx - 1]; } else { this.result.done = true; } this.result.value = newVal; return this.result; }; return BackwardsListIterator; }(ListIterator)); function backwards(l) { var _a; return _a = {}, _a[Symbol.iterator] = function () { return new BackwardsListIterator(l); }, _a; } exports.backwards = backwards; function emptyPushable() { return new List(0, 0, 0, [], undefined, []); } function push(value, l) { var suffixSize = getSuffixSize(l); if (l.length === 0) { l.bits = setPrefix(1, l.bits); l.prefix = [value]; } else if (suffixSize < 32) { l.bits = incrementSuffix(l.bits); l.suffix.push(value); } else if (l.root === undefined) { l.root = new Node(undefined, l.suffix); l.suffix = [value]; l.bits = setSuffix(1, l.bits); } else { var newNode = new Node(undefined, l.suffix); var index = l.length - 1 - 32 + 1; var current = l.root; var depth = getDepth(l); l.suffix = [value]; l.bits = setSuffix(1, l.bits); if (index - 1 < Math.pow(branchingFactor, (depth + 1))) { for (; depth >= 0; --depth) { var path = (index >> (depth * branchBits)) & mask; if (path < current.array.length) { current = current.array[path]; } else { current.array.push(createPath(depth - 1, newNode)); break; } } } else { l.bits = incrementDepth(l.bits); l.root = new Node(undefined, [l.root, createPath(depth, newNode)]); } } l.length++; return l; } function list() { var elements = []; for (var _i = 0; _i < arguments.length; _i++) { elements[_i] = arguments[_i]; } var l = emptyPushable(); for (var _a = 0, elements_1 = elements; _a < elements_1.length; _a++) { var element = elements_1[_a]; push(element, l); } return l; } exports.list = list; function empty() { return new List(0, 0, 0, emptyAffix, undefined, emptyAffix); } exports.empty = empty; function of(a) { return list(a); } exports.of = of; function pair(first, second) { return new List(2, 0, 2, emptyAffix, undefined, [first, second]); } exports.pair = pair; function from(sequence) { var l = emptyPushable(); if (sequence.length > 0 && (sequence[0] !== undefined || 0 in sequence)) { for (var i = 0; i < sequence.length; ++i) { push(sequence[i], l); } } else if (Symbol.iterator in sequence) { var iterator = sequence[Symbol.iterator](); var cur = void 0; while (!(cur = iterator.next()).done) { push(cur.value, l); } } return l; } exports.from = from; function range(start, end) { var list = emptyPushable(); for (var i = start; i < end; ++i) { push(i, list); } return list; } exports.range = range; function repeat(value, times) { var l = emptyPushable(); while (--times >= 0) { push(value, l); } return l; } exports.repeat = repeat; function times(func, times) { var l = emptyPushable(); for (var i = 0; i < times; i++) { push(func(i), l); } return l; } exports.times = times; function nodeNthDense(node, depth, index) { var current = node; for (; depth >= 0; --depth) { current = current.array[(index >> (depth * branchBits)) & mask]; } return current; } function handleOffset(depth, offset, index) { index += offset; for (; depth >= 0; --depth) { index = index - (offset & (mask << (depth * branchBits))); if (((index >> (depth * branchBits)) & mask) !== 0) { break; } } return index; } function nodeNth(node, depth, offset, index) { var path; var current = node; while (current.sizes !== undefined) { path = (index >> (depth * branchBits)) & mask; while (current.sizes[path] <= index) { path++; } if (path !== 0) { index -= current.sizes[path - 1]; offset = 0; } depth--; current = current.array[path]; } return nodeNthDense(current, depth, offset === 0 ? index : handleOffset(depth, offset, index)); } function nth(index, l) { if (index < 0 || l.length <= index) { return undefined; } var prefixSize = getPrefixSize(l); var suffixSize = getSuffixSize(l); if (index < prefixSize) { return l.prefix[prefixSize - index - 1]; } else if (index >= l.length - suffixSize) { return l.suffix[index - (l.length - suffixSize)]; } var offset = l.offset; var depth = getDepth(l); return l.root.sizes === undefined ? nodeNthDense(l.root, depth, offset === 0 ? index - prefixSize : handleOffset(depth, offset, index - prefixSize)) : nodeNth(l.root, depth, offset, index - prefixSize); } exports.nth = nth; function setSizes(node, height) { var sum = 0; var sizeTable = []; for (var i = 0; i < node.array.length; ++i) { sum += sizeOfSubtree(node.array[i], height - 1); sizeTable[i] = sum; } node.sizes = sizeTable; return node; } function sizeOfSubtree(node, height) { if (height !== 0) { if (node.sizes !== undefined) { return arrayLast(node.sizes); } else { var lastSize = sizeOfSubtree(arrayLast(node.array), height - 1); return ((node.array.length - 1) << (height * branchBits)) + lastSize; } } else { return node.array.length; } } function affixPush(a, array, length) { if (array.length === length) { array.push(a); return array; } else { var newArray = []; copyIndices(array, 0, newArray, 0, length); newArray.push(a); return newArray; } } function prepend(value, l) { var prefixSize = getPrefixSize(l); if (prefixSize < 32) { return new List(incrementPrefix(l.bits), l.offset, l.length + 1, affixPush(value, l.prefix, prefixSize), l.root, l.suffix); } else { var newList = cloneList(l); prependNodeToTree(newList, reverseArray(l.prefix)); var newPrefix = [value]; newList.prefix = newPrefix; newList.length++; newList.bits = setPrefix(1, newList.bits); return newList; } } exports.prepend = prepend; function copyLeft(l, k) { var currentNode = cloneNode(l.root); l.root = currentNode; for (var i = 1; i < k; ++i) { var index = 0; if (currentNode.sizes !== undefined) { for (var i_1 = 0; i_1 < currentNode.sizes.length; ++i_1) { currentNode.sizes[i_1] += 32; } } var newNode = cloneNode(currentNode.array[index]); currentNode.array[index] = newNode; currentNode = newNode; } return currentNode; } function nodePrepend(value, size, node) { var array = arrayPrepend(value, node.array); var sizes = undefined; if (node.sizes !== undefined) { sizes = new Array(node.sizes.length + 1); sizes[0] = size; for (var i = 0; i < node.sizes.length; ++i) { sizes[i + 1] = node.sizes[i] + size; } } return new Node(sizes, array); } function prependTopTree(l, depth, node) { var newOffset; if (l.root.array.length < branchingFactor) { newOffset = Math.pow(32, depth) - 32; l.root = new Node(undefined, arrayPrepend(createPath(depth - 1, node), l.root.array)); } else { l.bits = incrementDepth(l.bits); var sizes = l.root.sizes === undefined ? undefined : [32, arrayLast(l.root.sizes) + 32]; newOffset = depth === 0 ? 0 : Math.pow(32, (depth + 1)) - 32; l.root = new Node(sizes, [createPath(depth, node), l.root]); } return newOffset; } function prependNodeToTree(l, array) { if (l.root === undefined) { if (getSuffixSize(l) === 0) { l.bits = setSuffix(array.length, l.bits); l.suffix = array; } else { l.root = new Node(undefined, array); } return l; } else { var node = new Node(undefined, array); var depth = getDepth(l); var newOffset_1 = 0; if (l.root.sizes === undefined) { if (l.offset !== 0) { newOffset_1 = l.offset - branchingFactor; l.root = prependDense(l.root, depth, l.offset, node); } else { newOffset_1 = prependTopTree(l, depth, node); } } else { var copyableCount = 0; var nodesTraversed = 0; var currentNode = l.root; while (currentNode.sizes !== undefined && nodesTraversed < depth) { ++nodesTraversed; if (currentNode.array.length < 32) { copyableCount = nodesTraversed; } currentNode = currentNode.array[0]; } if (l.offset !== 0) { var copiedNode = copyLeft(l, nodesTraversed); for (var i = 0; i < copiedNode.sizes.length; ++i) { copiedNode.sizes[i] += branchingFactor; } copiedNode.array[0] = prependDense(copiedNode.array[0], depth - nodesTraversed, l.offset, node); l.offset = l.offset - branchingFactor; return l; } else { if (copyableCount === 0) { l.offset = prependTopTree(l, depth, node); } else { var parent_1; var prependableNode = void 0; if (copyableCount > 1) { parent_1 = copyLeft(l, copyableCount - 1); prependableNode = parent_1.array[0]; } else { parent_1 = undefined; prependableNode = l.root; } var path = createPath(depth - copyableCount, node); l.offset = Math.pow(32, (depth - copyableCount + 1)) - 32; var prepended = nodePrepend(path, 32, prependableNode); if (parent_1 === undefined) { l.root = prepended; } else { parent_1.array[0] = prepended; } } return l; } } l.offset = newOffset_1; return l; } } function prependDense(node, depth, offset, value) { var curOffset = (offset >> (depth * branchBits)) & mask; var path = (((offset - 1) >> (depth * branchBits)) & mask) - curOffset; if (path < 0) { return new Node(undefined, arrayPrepend(createPath(depth - 1, value), node.array)); } else { var array = copyArray(node.array); array[0] = prependDense(array[0], depth - 1, offset, value); return new Node(undefined, array); } } function append(value, l) { var suffixSize = getSuffixSize(l); if (suffixSize < 32) { return new List(incrementSuffix(l.bits), l.offset, l.length + 1, l.prefix, l.root, affixPush(value, l.suffix, suffixSize)); } var newSuffix = [value]; var newList = cloneList(l); appendNodeToTree(newList, l.suffix); newList.suffix = newSuffix; newList.length++; newList.bits = setSuffix(1, newList.bits); return newList; } exports.append = append; function length(l) { return l.length; } exports.length = length; function first(l) { var prefixSize = getPrefixSize(l); return prefixSize !== 0 ? l.prefix[prefixSize - 1] : l.length !== 0 ? l.suffix[0] : undefined; } exports.first = first; exports.head = first; function last(l) { var suffixSize = getSuffixSize(l); return suffixSize !== 0 ? l.suffix[suffixSize - 1] : l.length !== 0 ? l.prefix[0] : undefined; } exports.last = last; function mapArray(f, array) { var result = new Array(array.length); for (var i = 0; i < array.length; ++i) { result[i] = f(array[i]); } return result; } function mapNode(f, node, depth) { if (depth !== 0) { var array = node.array; var result = new Array(array.length); for (var i = 0; i < array.length; ++i) { result[i] = mapNode(f, array[i], depth - 1); } return new Node(node.sizes, result); } else { return new Node(undefined, mapArray(f, node.array)); } } function mapPrefix(f, prefix, length) { var newPrefix = new Array(length); for (var i = length - 1; 0 <= i; --i) { newPrefix[i] = f(prefix[i]); } return newPrefix; } function mapAffix(f, suffix, length) { var newSuffix = new Array(length); for (var i = 0; i < length; ++i) { newSuffix[i] = f(suffix[i]); } return newSuffix; } function map(f, l) { return new List(l.bits, l.offset, l.length, mapPrefix(f, l.prefix, getPrefixSize(l)), l.root === undefined ? undefined : mapNode(f, l.root, getDepth(l)), mapAffix(f, l.suffix, getSuffixSize(l))); } exports.map = map; function pluck(key, l) { return map(function (a) { return a[key]; }, l); } exports.pluck = pluck; function foldlSuffix(f, acc, array, length) { for (var i = 0; i < length; ++i) { acc = f(acc, array[i]); } return acc; } function foldlPrefix(f, acc, array, length) { for (var i = length - 1; 0 <= i; --i) { acc = f(acc, array[i]); } return acc; } function foldlNode(f, acc, node, depth) { var array = node.array; if (depth === 0) { return foldlSuffix(f, acc, array, array.length); } for (var i = 0; i < array.length; ++i) { acc = foldlNode(f, acc, array[i], depth - 1); } return acc; } function foldl(f, initial, l) { var suffixSize = getSuffixSize(l); var prefixSize = getPrefixSize(l); initial = foldlPrefix(f, initial, l.prefix, prefixSize); if (l.root !== undefined) { initial = foldlNode(f, initial, l.root, getDepth(l)); } return foldlSuffix(f, initial, l.suffix, suffixSize); } exports.foldl = foldl; exports.reduce = foldl; function traverse(of, f, l) { return foldr(function (a, fl) { return fl["fantasy-land/ap"](f(a)["fantasy-land/map"](function (a) { return function (l) { return prepend(a, l); }; })); }, of["fantasy-land/of"](empty()), l); } exports.traverse = traverse; function sequence(ofObj, l) { return traverse(ofObj, function (a) { return a; }, l); } exports.sequence = sequence; function scan(f, initial, l) { return foldl(function (l2, a) { return push(f(last(l2), a), l2); }, push(initial, emptyPushable()), l); } exports.scan = scan; function forEach(callback, l) { foldl(function (_, element) { return callback(element); }, undefined, l); } exports.forEach = forEach; function filter(predicate, l) { return foldl(function (acc, a) { return (predicate(a) ? push(a, acc) : acc); }, emptyPushable(), l); } exports.filter = filter; function reject(predicate, l) { return foldl(function (acc, a) { return (predicate(a) ? acc : push(a, acc)); }, emptyPushable(), l); } exports.reject = reject; function partition(predicate, l) { return foldl(function (arr, a) { return (predicate(a) ? push(a, arr[0]) : push(a, arr[1]), arr); }, [emptyPushable(), emptyPushable()], l); } exports.partition = partition; function join(separator, l) { return foldl(function (a, b) { return (a.length === 0 ? b : a + separator + b); }, "", l); } exports.join = join; function foldrSuffix(f, initial, array, length) { var acc = initial; for (var i = length - 1; 0 <= i; --i) { acc = f(array[i], acc); } return acc; } function foldrPrefix(f, initial, array, length) { var acc = initial; for (var i = 0; i < length; ++i) { acc = f(array[i], acc); } return acc; } function foldrNode(f, initial, _a, depth) { var array = _a.array; if (depth === 0) { return foldrSuffix(f, initial, array, array.length); } var acc = initial; for (var i = array.length - 1; 0 <= i; --i) { acc = foldrNode(f, acc, array[i], depth - 1); } return acc; } function foldr(f, initial, l) { var suffixSize = getSuffixSize(l); var prefixSize = getPrefixSize(l); var acc = foldrSuffix(f, initial, l.suffix, suffixSize); if (l.root !== undefined) { acc = foldrNode(f, acc, l.root, getDepth(l)); } return foldrPrefix(f, acc, l.prefix, prefixSize); } exports.foldr = foldr; exports.reduceRight = foldr; function ap(listF, l) { return flatten(map(function (f) { return map(f, l); }, listF)); } exports.ap = ap; function flatten(nested) { return foldl(concat, empty(), nested); } exports.flatten = flatten; function flatMap(f, l) { return flatten(map(f, l)); } exports.flatMap = flatMap; exports.chain = flatMap; function foldlArrayCb(cb, state, array, from, to) { for (var i = from; i < to && cb(array[i], state); ++i) { } return i === to; } function foldrArrayCb(cb, state, array, from, to) { for (var i = from - 1; to <= i && cb(array[i], state); --i) { } return i === to - 1; } function foldlNodeCb(cb, state, node, depth) { var array = node.array; if (depth === 0) { return foldlArrayCb(cb, state, array, 0, array.length); } var to = array.length; for (var i = 0; i < to; ++i) { if (!foldlNodeCb(cb, state, array[i], depth - 1)) { return false; } } return true; } function foldlCb(cb, state, l) { var prefixSize = getPrefixSize(l); if (!foldrArrayCb(cb, state, l.prefix, prefixSize, 0) || (l.root !== undefined && !foldlNodeCb(cb, state, l.root, getDepth(l)))) { return state; } var suffixSize = getSuffixSize(l); foldlArrayCb(cb, state, l.suffix, 0, suffixSize); return state; } function foldrNodeCb(cb, state, node, depth) { var array = node.array; if (depth === 0) { return foldrArrayCb(cb, state, array, array.length, 0); } for (var i = array.length - 1; 0 <= i; --i) { if (!foldrNodeCb(cb, state, array[i], depth - 1)) { return false; } } return true; } function foldrCb(cb, state, l) { var suffixSize = getSuffixSize(l); var prefixSize = getPrefixSize(l); if (!foldrArrayCb(cb, state, l.suffix, suffixSize, 0) || (l.root !== undefined && !foldrNodeCb(cb, state, l.root, getDepth(l)))) { return state; } var prefix = l.prefix; foldlArrayCb(cb, state, l.prefix, prefix.length - prefixSize, prefix.length); return state; } function foldlWhileCb(a, state) { if (state.predicate(state.result, a) === false) { return false; } state.result = state.f(state.result, a); return true; } function foldlWhile(predicate, f, initial, l) { return foldlCb(foldlWhileCb, { predicate: predicate, f: f, result: initial }, l).result; } exports.foldlWhile = foldlWhile; exports.reduceWhile = foldlWhile; function everyCb(value, state) { return (state.result = state.predicate(value)); } function every(predicate, l) { return foldlCb(everyCb, { predicate: predicate, result: true }, l).result; } exports.every = every; exports.all = every; function someCb(value, state) { return !(state.result = state.predicate(value)); } function some(predicate, l) { return foldlCb(someCb, { predicate: predicate, result: false }, l).result; } exports.some = some; exports.any = some; function none(predicate, l) { return !some(predicate, l); } exports.none = none; function findCb(value, state) { if (state.predicate(value)) { state.result = value; return false; } else { return true; } } function find(predicate, l) { return foldlCb(findCb, { predicate: predicate, result: undefined }, l) .result; } exports.find = find; function findLast(predicate, l) { return foldrCb(findCb, { predicate: predicate, result: undefined }, l) .result; } exports.findLast = findLast; function indexOfCb(value, state) { ++state.index; return !(state.found = elementEquals(value, state.element)); } function indexOf(element, l) { var state = { element: element, found: false, index: -1 }; foldlCb(indexOfCb, state, l); return state.found ? state.index : -1; } exports.indexOf = indexOf; function lastIndexOf(element, l) { var state = { element: element, found: false, index: 0 }; foldrCb(indexOfCb, state, l); return state.found ? l.length - state.index : -1; } exports.lastIndexOf = lastIndexOf; function findIndexCb(value, state) { ++state.index; return !(state.found = state.predicate(value)); } function findIndex(predicate, l) { var _a = foldlCb(findIndexCb, { predicate: predicate, found: false, index: -1 }, l), found = _a.found, index = _a.index; return found ? index : -1; } exports.findIndex = findIndex; var containsState = { element: undefined, result: false }; function containsCb(value, state) { return !(state.result = value === state.element); } function includes(element, l) { containsState.element = element; containsState.result = false; return foldlCb(containsCb, containsState, l).result; } exports.includes = includes; exports.contains = includes; function equalsCb(value2, state) { var value = state.iterator.next().value; return (state.equals = state.f(value, value2)); } function equals(l1, l2) { return equalsWith(elementEquals, l1, l2); } exports.equals = equals; function equalsWith(f, l1, l2) { if (l1 === l2) { return true; } else if (l1.length !== l2.length) { return false; } else { var s = { iterator: l2[Symbol.iterator](), equals: true, f: f }; return foldlCb(equalsCb, s, l1).equals; } } exports.equalsWith = equalsWith; var eMax = 2; function createConcatPlan(array) { var sizes = []; var sum = 0; for (var i_2 = 0; i_2 < array.length; ++i_2) { sum += array[i_2].array.length; sizes[i_2] = array[i_2].array.length; } var optimalLength = Math.ceil(sum / branchingFactor); var n = array.length; var i = 0; if (optimalLength + eMax >= n) { return undefined; } while (optimalLength + eMax < n) { while (sizes[i] > branchingFactor - eMax / 2) { ++i; } var remaining = sizes[i]; do { var size = Math.min(remaining + sizes[i + 1], branchingFactor); sizes[i] = size; remaining = remaining - (size - sizes[i + 1]); ++i; } while (remaining > 0); for (var j = i; j <= n - 1; ++j) { sizes[j] = sizes[j + 1]; } --i; --n; } sizes.length = n; return sizes; } function concatNodeMerge(left, center, right) { var array = []; if (left !== undefined) { for (var i = 0; i < left.array.length - 1; ++i) { array.push(left.array[i]); } } for (var i = 0; i < center.array.length; ++i) { array.push(center.array[i]); } if (right !== undefined) { for (var i = 1; i < right.array.length; ++i) { array.push(right.array[i]); } } return array; } function executeConcatPlan(merged, plan, height) { var result = []; var sourceIdx = 0; var offset = 0; for (var _i = 0, plan_1 = plan; _i < plan_1.length; _i++) { var toMove = plan_1[_i]; var source = merged[sourceIdx].array; if (toMove === source.length && offset === 0) { result.push(merged[sourceIdx]); ++sourceIdx; } else { var node = new Node(undefined, []); while (toMove > 0) { var available = source.length - offset; var itemsToCopy = Math.min(toMove, available); pushElements(source, node.array, offset, itemsToCopy); if (toMove >= available) { ++sourceIdx; source = merged[sourceIdx].array; offset = 0; } else { offset += itemsToCopy; } toMove -= itemsToCopy; } if (height > 1) { setSizes(node, height - 1); } result.push(node); } } return result; } function rebalance(left, center, right, height, top) { var merged = concatNodeMerge(left, center, right); var plan = createConcatPlan(merged); var balanced = plan !== undefined ? executeConcatPlan(merged, plan, height) : merged; if (balanced.length <= branchingFactor) { if (top === true) { return new Node(undefined, balanced); } else { return new Node(undefined, [ setSizes(new Node(undefined, balanced), height) ]); } } else { return new Node(undefined, [ setSizes(new Node(undefined, balanced.slice(0, branchingFactor)), height), setSizes(new Node(undefined, balanced.slice(branchingFactor)), height) ]); } } function concatSubTree(left, lDepth, right, rDepth, isTop) { if (lDepth > rDepth) { var c = concatSubTree(arrayLast(left.array), lDepth - 1, right, rDepth, false); return rebalance(left, c, undefined, lDepth, isTop); } else if (lDepth < rDepth) { var c = concatSubTree(left, lDepth, arrayFirst(right.array), rDepth - 1, false); return rebalance(undefined, c, right, rDepth, isTop); } else if (lDepth === 0) { return new Node(undefined, [left, right]); } else { var c = concatSubTree(arrayLast(left.array), lDepth - 1, arrayFirst(right.array), rDepth - 1, false); return rebalance(left, c, right, lDepth, isTop); } } function getHeight(node) { if (node.array[0] instanceof Node) { return 1 + getHeight(node.array[0]); } else { return 0; } } function appendNodeToTree(l, array) { if (l.root === undefined) { if (getPrefixSize(l) === 0) { l.bits = setPrefix(array.length, l.bits); l.prefix = reverseArray(array); } else { l.root = new Node(undefined, array); } return l; } var depth = getDepth(l); var index = handleOffset(depth, l.offset, l.length - 1 - getPrefixSize(l)); var nodesToCopy = 0; var nodesVisited = 0; var shift = depth * 5; var currentNode = l.root; if (Math.pow(32, (depth + 1)) < index) { shift = 0; nodesVisited = depth; } while (shift > 5) { var childIndex = void 0; if (currentNode.sizes === undefined) { childIndex = (index >> shift) & mask; index &= ~(mask << shift); } else { childIndex = currentNode.array.length - 1; index -= currentNode.sizes[childIndex - 1]; } nodesVisited++; if (childIndex < mask) { nodesToCopy = nodesVisited; } currentNode = currentNode.array[childIndex]; if (currentNode === undefined) { nodesToCopy = nodesVisited; shift = 5; } shift -= 5; } if (shift !== 0) { nodesVisited++; if (currentNode.array.length < branchingFactor) { nodesToCopy = nodesVisited; } } var node = new Node(undefined, array); if (nodesToCopy === 0) { var newPath = nodesVisited === 0 ? node : createPath(nodesVisited, node); var newRoot = new Node(undefined, [l.root, newPath]); l.root = newRoot; l.bits = incrementDepth(l.bits); } else { var copiedNode = copyFirstK(l, nodesToCopy, array.length); copiedNode.array.push(createPath(depth - nodesToCopy, node)); } return l; } function copyFirstK(newList, k, leafSize) { var currentNode = cloneNode(newList.root); newList.root = currentNode; for (var i = 1; i < k; ++i) { var index = currentNode.array.length - 1; if (currentNode.sizes !== undefined) { currentNode.sizes[index] += leafSize; } var newNode = cloneNode(currentNode.array[index]); currentNode.array[index] = newNode; currentNode = newNode; } if (currentNode.sizes !== undefined) { currentNode.sizes.push(arrayLast(currentNode.sizes) + leafSize); } return currentNode; } var concatBuffer = new Array(3); function concatAffixes(left, right) { var nr = 0; var arrIdx = 0; var i = 0; var length = getSuffixSize(left); concatBuffer[nr] = []; for (i = 0; i < length; ++i) { concatBuffer[nr][arrIdx++] = left.suffix[i]; } length = getPrefixSize(right); for (i = 0; i < length; ++i) { if (arrIdx === 32) { arrIdx = 0; ++nr; concatBuffer[nr] = []; } concatBuffer[nr][arrIdx++] = right.prefix[length - 1 - i]; } length = getSuffixSize(right); for (i = 0; i < length; ++i) { if (arrIdx === 32) { arrIdx = 0; ++nr; concatBuffer[nr] = []; } concatBuffer[nr][arrIdx++] = right.suffix[i]; } return nr; } function concat(left, right) { if (left.length === 0) { return right; } else if (right.length === 0) { return left; } var newSize = left.length + right.length; var rightSuffixSize = getSuffixSize(right); var newList = cloneList(left); if (right.root === undefined) { var nrOfAffixes = concatAffixes(left, right); for (var i = 0; i < nrOfAffixes; ++i) { newList = appendNodeToTree(newList, concatBuffer[i]); newList.length += concatBuffer[i].length; concatBuffer[i] = undefined; } newList.length = newSize; newList.suffix = concatBuffer[nrOfAffixes]; newList.bits = setSuffix(concatBuffer[nrOfAffixes].length, newList.bits); concatBuffer[nrOfAffixes] = undefined; return newList; } else { var leftSuffixSize = getSuffixSize(left); if (leftSuffixSize > 0) { newList = appendNodeToTree(newList, left.suffix.slice(0, leftSuffixSize)); newList.length += leftSuffixSize; } newList = appendNodeToTree(newList, right.prefix.slice(0, getPrefixSize(right)).reverse()); var newNode = concatSubTree(newList.root, getDepth(newList), right.root, getDepth(right), true); var newDepth = getHeight(newNode); setSizes(newNode, newDepth); newList.root = newNode; newList.offset &= ~(mask << (getDepth(left) * branchBits)); newList.length = newSize; newList.bits = setSuffix(rightSuffixSize, setDepth(newDepth, newList.bits)); newList.suffix = right.suffix; return newList; } } exports.concat = concat; function update(index, a, l) { if (index < 0 || l.length <= index) { return l; } var prefixSize = getPrefixSize(l); var suffixSize = getSuffixSize(l); var newList = cloneList(l); if (index < prefixSize) { var newPrefix = copyArray(newList.prefix); newPrefix[newPrefix.length - index - 1] = a; newList.prefix = newPrefix; } else if (index >= l.length - suffixSize) { var newSuffix = copyArray(newList.suffix); newSuffix[index - (l.length - suffixSize)] = a; newList.suffix = newSuffix; } else { newList.root = updateNode(l.root, getDepth(l), index - prefixSize, l.offset, a); } return newList; } exports.update = update; function adjust(index, f, l) { if (index < 0 || l.length <= index) { return l; } return update(index, f(nth(index, l)), l); } exports.adjust = adjust; var newAffix; function sliceNode(node, index, depth, pathLeft, pathRight, childLeft, childRight) { var array = node.array.slice(pathLeft, pathRight + 1); if (childLeft !== undefined) { array[0] = childLeft; } if (childRight !== undefined) { array[array.length - 1] = childRight; } var sizes = node.sizes; if (sizes !== undefined) { sizes = sizes.slice(pathLeft, pathRight + 1); var slicedOffLeft = pathLeft !== 0 ? node.sizes[pathLeft - 1] : 0; if (childLeft !== undefined) { if (childLeft.sizes !== undefined) { var oldChild = node.array[pathLeft]; slicedOffLeft += arrayLast(oldChild.sizes) - arrayLast(childLeft.sizes); } else { slicedOffLeft += ((index - slicedOffLeft) & ~31) + 32; } } for (var i = 0; i < sizes.length; ++i) { sizes[i] -= slicedOffLeft; } if (childRight !== undefined) { var slicedOffRight = sizeOfSubtree(node.array[pathRight], depth - 1) - sizeOfSubtree(childRight, depth - 1); sizes[sizes.length - 1] -= slicedOffRight; } } return new Node(sizes, array); } var newOffset = 0; function sliceLeft(tree, depth, index, offset, top) { var _a = getPath(index, offset, depth, tree.sizes), path = _a.path, newIndex = _a.index, updatedOffset = _a.updatedOffset; if (depth === 0) { newAffix = tree.array.slice(path).reverse(); return undefined; } else { var child = sliceLeft(tree.array[path], depth - 1, newIndex, updatedOffset, false); if (child === undefined) { ++path; if (path === tree.array.length) { return undefined; } } if (tree.sizes === undefined && top === false) { newOffset |= (32 - (tree.array.length - path)) << (depth * branchBits); } return sliceNode(tree, index, depth, path, tree.array.length - 1, child, undefined); } } function sliceRight(node, depth, index, offset) { var _a = getPath(index, offset, depth, node.sizes), path = _a.path, newIndex = _a.index; if (depth === 0) { newAffix = node.array.slice(0, path + 1); return undefined; } else { var child = sliceRight(node.array[path], depth - 1, newIndex, path === 0 ? offset : 0); if (child === undefined) { --path; if (path === -1) { return undefined; } } var array = node.array.slice(0, path + 1); if (child !== undefined) { array[array.length - 1] = child; } var sizes = node.sizes; if (sizes !== undefined) { sizes = sizes.slice(0, path + 1); if (child !== undefined) { var slicedOff = sizeOfSubtree(node.array[path], depth - 1) - sizeOfSubtree(child, depth - 1); sizes[sizes.length - 1] -= slicedOff; } } return new Node(sizes, array); } } function sliceTreeList(from, to, tree, depth, offset, l) { var sizes = tree.sizes; var _a = getPath(from, offset, depth, sizes), pathLeft = _a.path, newFrom = _a.index; var _b = getPath(to, offset, depth, sizes), pathRight = _b.path, newTo = _b.index; if (depth === 0) { l.prefix = emptyAffix; l.suffix = tree.array.slice(pathLeft, pathRight + 1); l.root = undefined; l.bits = setSuffix(pathRight - pathLeft + 1, 0); return l; } else if (pathLeft === pathRight) { l.bits = decrementDepth(l.bits); return sliceTreeList(newFrom, newTo, tree.array[pathLeft], depth - 1, pathLeft === 0 ? offset : 0, l); } else { var childRight = sliceRight(tree.array[pathRight], depth - 1, newTo, 0); l.bits = setSuffix(newAffix.length, l.bits); l.suffix = newAffix; if (childRight === undefined) { --pathRight; } newOffset = 0; var childLeft = sliceLeft(tree.array[pathLeft], depth - 1, newFrom, pathLeft === 0 ? offset : 0, pathLeft === pathRight); l.offset = newOffset; l.bits = setPrefix(newAffix.length, l.bits); l.prefix = newAffix; if (childLeft === undefined) { ++pathLeft; } if (pathLeft >= pathRight) { if (pathLeft > pathRight) { l.bits = setDepth(0, l.bits); l.root = undefined; } else { l.bits = decrementDepth(l.bits); var newRoot = childRight !== undefined ? childRight : childLeft !== undefined ? childLeft : tree.array[pathLeft]; l.root = new Node(newRoot.sizes, newRoot.array); } } else { l.root = sliceNode(tree, from, depth, pathLeft, pathRight, childLeft, childRight); } return l; } } function slice(from, to, l) { var bits = l.bits, length = l.length; to = Math.min(length, to); if (from < 0) { from = length + from; } if (to < 0) { to = length + to; } if (to <= from || to <= 0 || length <= from) { return empty(); } if (from <= 0 && length <= to) { return l; } var newLength = to - from; var prefixSize = getPrefixSize(l); var suffixSize = getSuffixSize(l); if (to <= prefixSize) { return new List(setPrefix(newLength, 0), 0, newLength, l.prefix.slice(prefixSize - to, prefixSize - from), undefined, emptyAffix); } var suffixStart = length - suffixSize; if (suffixStart <= from) { return new List(setSuffix(newLength, 0), 0, newLength, emptyAffix, undefined, l.suffix.slice(from - suffixStart, to - suffixStart)); } var newList = cloneList(l); newList.length = newLength; if (prefixSize <= from && to <= suffixStart) { sliceTreeList(from - prefixSize + l.offset, to - prefixSize + l.offset - 1, l.root, getDepth(l), l.offset, newList); return newList; } if (0 < from) { if (from < prefixSize) { newList.prefix = l.prefix.slice(0, prefixSize - from); bits = setPrefix(prefixSize - from, bits); } else { newOffset = 0; newList.root = sliceLeft(newList.root, getDepth(l), from - prefixSize, l.offset, true); newList.offset = newOffset; if (newList.root === undefined) { bits = setDepth(0, bits); } bits = setPrefix(newAffix.length, bits); prefixSize = newAffix.length; newList.prefix = newAffix; } } if (to < length) { if (length - to < suffixSize) { bits = setSuffix(suffixSize - (length - to), bits); newList.suffix = l.suffix.slice(0, suffixSize - (length - to)); } else { newList.root = sliceRight(newList.root, getDepth(l), to - prefixSize - 1, newList.offset); if (newList.root === undefined) { bits = setDepth(0, bits); newList.offset = 0; } bits = setSuffix(newAffix.length, bits); newList.suffix = newAffix; } } newList.bits = bits; return newList; } exports.slice = slice; function take(n, l) { return slice(0, n, l); } exports.take = take; function findNotIndexCb(value, state) { if (state.predicate(value)) { ++state.index; return true; } else { return false; } } function takeWhile(predicate, l) { var index = foldlCb(findNotIndexCb, { predicate: predicate, index: 0 }, l).index; return slice(0, index, l); } exports.takeWhile = takeWhile; function takeLastWhile(predicate, l) { var index = foldrCb(findNotIndexCb, { predicate: predicate, index: 0 }, l).index; return slice(l.length - index, l.length, l); } exports.takeLastWhile = takeLastWhile; function dropWhile(predicate, l) { var index = foldlCb(findNotIndexCb, { predicate: predicate, index: 0 }, l).index; return slice(index, l.length, l); } exports.dropWhile = dropWhile; function dropRepeats(l) { return dropRepeatsWith(elementEquals, l); } exports.dropRepeats = dropRepeats; function dropRepeatsWith(predicate, l) { return foldl(function (acc, a) { return acc.length !== 0 && predicate(last(acc), a) ? acc : push(a, acc); }, emptyPushable(), l); } exports.dropRepeatsWith = dropRepeatsWith; function takeLast(n, l) { return slice(l.length - n, l.length, l); } exports.takeLast = takeLast; function splitAt(index, l) { return [slice(0, index, l), slice(index, l.length, l)]; } exports.splitAt = splitAt; function splitWhen(predicate, l) { var idx = findIndex(predicate, l); return idx === -1 ? [l, empty()] : splitAt(idx, l); } exports.splitWhen = splitWhen; function splitEvery(size, l) { var _a = foldl(function (_a, elm) { var l2 = _a.l2, buffer = _a.buffer; push(elm, buffer); if (buffer.length === size) { return { l2: push(buffer, l2), buffer: emptyPushable() }; } else { return { l2: l2, buffer: buffer }; } }, { l2: emptyPushable(), buffer: emptyPushable() }, l), l2 = _a.l2, buffer = _a.buffer; return buffer.length === 0 ? l2 : push(buffer, l2); } exports.splitEvery = splitEvery; function remove(from, amount, l) { return concat(slice(0, from, l), slice(from + amount, l.length, l)); } exports.remove = remove; function drop(n, l) { return slice(n, l.length, l); } exports.drop = drop; function d