Skip to content
Snippets Groups Projects
Select Git revision
  • 9f2053e68d0619f2ed92a9112d7d685fb360e8d8
  • master default protected
  • rednatco-v2
  • rednatco
  • test
  • ntc-tube-uniform-color
  • ntc-tube-missing-atoms
  • restore-vertex-array-per-program
  • watlas2
  • dnatco_new
  • cleanup-old-nodejs
  • webmmb
  • fix_auth_seq_id
  • update_deps
  • ext_dev
  • ntc_balls
  • nci-2
  • plugin
  • bugfix-0.4.5
  • nci
  • servers
  • v0.5.0-dev.1
  • v0.4.5
  • v0.4.4
  • v0.4.3
  • v0.4.2
  • v0.4.1
  • v0.4.0
  • v0.3.12
  • v0.3.11
  • v0.3.10
  • v0.3.9
  • v0.3.8
  • v0.3.7
  • v0.3.6
  • v0.3.5
  • v0.3.4
  • v0.3.3
  • v0.3.2
  • v0.3.1
  • v0.3.0
41 results

iterator.ts

Blame
  • iterator.ts 3.24 KiB
    /**
     * 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