123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- /**
- * Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author David Sehnal <david.sehnal@gmail.com>
- */
- /**
- * "Idiomatic" usage:
- *
- * const it = ...;
- * while (it.hasNext) { const v = it.move(); ... }
- */
- interface Iterator<T> {
- readonly hasNext: boolean,
- move(): T
- }
- class ArrayIteratorImpl<T> implements Iterator<T> {
- private xs: ArrayLike<T> = [];
- private index: number = -1;
- private length: number = 0;
- private lastValue: T;
- hasNext: boolean = false;
- move() {
- ++this.index;
- this.lastValue = this.xs[this.index];
- this.hasNext = this.index < this.length - 1;
- return this.lastValue;
- }
- constructor(xs: ArrayLike<T>) {
- this.length = xs.length;
- this.hasNext = xs.length > 0;
- this.xs = xs;
- this.index = -1;
- // try to avoid deoptimization with undefined values
- this.lastValue = xs.length > 0 ? xs[0] : void 0 as any;
- }
- }
- class RangeIteratorImpl implements Iterator<number> {
- private value: number = 0;
- hasNext: boolean = false;
- move() {
- ++this.value;
- this.hasNext = this.value < this.max;
- return this.value;
- }
- constructor(min: number, private max: number) {
- this.value = min - 1;
- this.hasNext = max >= min;
- }
- }
- class ValueIterator<T> implements Iterator<T> {
- hasNext = true;
- move() { this.hasNext = false; return this.value; }
- constructor(private value: T) { }
- }
- class MapIteratorImpl<T, R> implements Iterator<R> {
- hasNext: boolean = false;
- move() {
- const v = this.f(this.base.move());
- this.hasNext = this.base.hasNext;
- return v;
- }
- constructor(private base: Iterator<T>, private f: (v: T) => R) {
- this.hasNext = base.hasNext;
- }
- }
- class FilterIteratorImpl<T> implements Iterator<T> {
- private next: T;
- hasNext: boolean;
- move() {
- const ret = this.next;
- this.hasNext = this.findNext();
- return ret;
- }
- private findNext() {
- while (this.base.hasNext) {
- this.next = this.base.move();
- if (this.p(this.next)) return true;
- }
- return false;
- }
- constructor(private base: Iterator<T>, private p: (v: T) => boolean) {
- this.hasNext = this.findNext();
- }
- }
- namespace Iterator {
- export const Empty: Iterator<any> = new RangeIteratorImpl(0, -1);
- export function Array<T>(xs: ArrayLike<T>): Iterator<T> { return new ArrayIteratorImpl<T>(xs); }
- export function Value<T>(value: T): Iterator<T> { return new ValueIterator(value); }
- export function Range(min: number, max: number): Iterator<number> { return new RangeIteratorImpl(min, max); }
- export function map<T, R>(base: Iterator<T>, f: (v: T) => R): Iterator<R> { return new MapIteratorImpl(base, f); }
- export function filter<T>(base: Iterator<T>, p: (v: T) => boolean): Iterator<T> { return new FilterIteratorImpl(base, p); }
- // Iterate until first truthy value is returned.
- export function forEach<T, Ctx>(it: Iterator<T>, f: (v: T, ctx: Ctx) => any, ctx: Ctx): Ctx {
- while (it.hasNext) {
- const c = f(it.move(), ctx);
- if (c) return ctx;
- }
- return ctx;
- }
- }
- export default Iterator
|