"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
exports.Iterable = void 0;
(function(Iterable) {
  function is(thing) {
    return thing && typeof thing === "object" && typeof thing[Symbol.iterator] === "function";
  }
  Iterable.is = is;
  const _empty = Object.freeze([]);
  function empty() {
    return _empty;
  }
  Iterable.empty = empty;
  function* single(element) {
    yield element;
  }
  Iterable.single = single;
  function from(iterable) {
    return iterable || _empty;
  }
  Iterable.from = from;
  function isEmpty(iterable) {
    return !iterable || iterable[Symbol.iterator]().next().done === true;
  }
  Iterable.isEmpty = isEmpty;
  function first(iterable) {
    return iterable[Symbol.iterator]().next().value;
  }
  Iterable.first = first;
  function some(iterable, predicate) {
    for (const element of iterable) {
      if (predicate(element)) {
        return true;
      }
    }
    return false;
  }
  Iterable.some = some;
  function find(iterable, predicate) {
    for (const element of iterable) {
      if (predicate(element)) {
        return element;
      }
    }
    return void 0;
  }
  Iterable.find = find;
  function* filter(iterable, predicate) {
    for (const element of iterable) {
      if (predicate(element)) {
        yield element;
      }
    }
  }
  Iterable.filter = filter;
  function* map(iterable, fn) {
    let index = 0;
    for (const element of iterable) {
      yield fn(element, index++);
    }
  }
  Iterable.map = map;
  function* concat(...iterables) {
    for (const iterable of iterables) {
      for (const element of iterable) {
        yield element;
      }
    }
  }
  Iterable.concat = concat;
  function* concatNested(iterables) {
    for (const iterable of iterables) {
      for (const element of iterable) {
        yield element;
      }
    }
  }
  Iterable.concatNested = concatNested;
  function reduce(iterable, reducer, initialValue) {
    let value = initialValue;
    for (const element of iterable) {
      value = reducer(value, element);
    }
    return value;
  }
  Iterable.reduce = reduce;
  function* slice(arr, from2, to = arr.length) {
    if (from2 < 0) {
      from2 += arr.length;
    }
    if (to < 0) {
      to += arr.length;
    } else if (to > arr.length) {
      to = arr.length;
    }
    for (; from2 < to; from2++) {
      yield arr[from2];
    }
  }
  Iterable.slice = slice;
  function consume(iterable, atMost = Number.POSITIVE_INFINITY) {
    const consumed = [];
    if (atMost === 0) {
      return [consumed, iterable];
    }
    const iterator = iterable[Symbol.iterator]();
    for (let i = 0; i < atMost; i++) {
      const next = iterator.next();
      if (next.done) {
        return [consumed, Iterable.empty()];
      }
      consumed.push(next.value);
    }
    return [consumed, { [Symbol.iterator]() {
      return iterator;
    } }];
  }
  Iterable.consume = consume;
  function equals(a, b, comparator = (at, bt) => at === bt) {
    const ai = a[Symbol.iterator]();
    const bi = b[Symbol.iterator]();
    while (true) {
      const an = ai.next();
      const bn = bi.next();
      if (an.done !== bn.done) {
        return false;
      } else if (an.done) {
        return true;
      } else if (!comparator(an.value, bn.value)) {
        return false;
      }
    }
  }
  Iterable.equals = equals;
})(exports.Iterable || (exports.Iterable = {}));
