👔Iterable+ext

extends iterables with custom methods.

JSiterationiterable ⟩ extension

extends iterables with methods such as filter, map, take, ... etc.

👉 custom objects

// ⭐️ check if iterable
array.isIterable,    // true
object.isIterable,   // false
(3).isIterable,      // false

// ⭐️ extended methods
'xyz'.forEach(x => log(x));    // x, y, z
'abc'.map(x=>x+2).array,       // [ 'a2', 'b2', 'c2' ]
'abcdefg'.take(4).array,       // [ 'a', 'b', 'c', 'd' ]
'abcd'.some(x => x > 'm'),     // false

// ⭐️ (closed) range
range(0, 3).map(x => x * 2).array,     // [0, 2, 4, 6]
range(0, 10).every(x => x < 10),       // false
// 2023.01.21 - 18:42 (?) first recorded, rename Iterable+ext.js
// ----------------------------------------

//
// ⭐ Iterable + ext
// ----------------------------------------
// - range()
// ----------------------------------------
// 🔸 .isIterable   -> boolean
// 🔸 .array        -> array
// ----------------------------------------
// 🔹 .filter()     -> it
// 🔹 .map()        -> it
// 🔹 .take()       -> it
// 🔹 .reduce()     -> any
// ----------------------------------------
// 🔹 .every()      -> boolean
// 🔹 .some()       -> boolean
// 🔹 .forEach()    -> void
// 🔹 .toArray()    -> array
//
Object.defineProperties(Object.prototype, {

    // 🔸 obj.isIterable
    isIterable: {
        get() {
            return typeof this[Symbol.iterator] === 'function';
        }
    },

    // 🔸 it.array
    array: {
        get: function() {
            this._checkIterable();
            return [...this];
        }
    },

    // obj._iterableValues
    _checkIterable: {
        value: function() {
            // throw error if not iterable
            if (!this.isIterable) {
                throw new TypeError(`object is not iterable!`);
            }
        }
    },

    // 🔹 it.map(f)
    map: {
        value: function(f) {
            this._checkIterable();
            const values = this;
            // return a mapped iterable
            return {
                // make iterabor (by using generator function)
                *[Symbol.iterator]() {
                    for (const val of values) yield f(val);
                }
            }
        }
    },

    // 🔹 it.filter(f)
    filter: {
        value: function(condition) {
            this._checkIterable();
            const values = this;
            // return a filtered iterable
            return {
                // make iterabor (by using generator function)
                *[Symbol.iterator]() {
                    for (const val of values) if (condition(val)) yield val;
                }
            }
        }
    },

    // 🔹 it.take(n)
    take: {
        value: function(n) {
            this._checkIterable();
            const values = this;
            // return a partial iterable
            return {
                // make iterabor (by using generator function)
                *[Symbol.iterator]() {
                    for (const val of values) {
                        if (n > 0) {
                            n -= 1;
                            yield val;
                        } else { return }
                    }
                }
            }
        }
    },

    // 🔹 it.forEach(f)
    forEach: {
        value: function(f) {
            this._checkIterable();
            for (const val of this) f(val);
        }
    },

    // 🔹 it.reduce()
    reduce: {
        value: function(...args) {
            this._checkIterable();
            return [...this].reduce(...args);
        }
    },

    // 🔹 it.toArray()
    toArray: {
        value: function() {
            this._checkIterable();
            return [...this];
        }
    },

    // 🔹 it.every(condition)
    every: {
        value: function(condition) {
            this._checkIterable();
            for (const val of this) if (!condition(val)) return false;
            return true;
        }
    },

    // 🔹 it.some(condition)
    some: {
        value: function(condition) {
            this._checkIterable();
            for (const val of this) if (condition(val)) return true;
            return false;
        }
    },

});

// ⭐️ closed range: [start, end]
function range(start, end, step = start < end ? 1 : -1) {
    
    function isInRange(i) {
        return (step > 0) ? (start <= i && i <= end) : (end <= i && i <= start);
    }
    
    // return an iterable
    return {
        *[Symbol.iterator]() {
            for (let i = start; isInRange(i) ; i += step) {
                yield i;
            }
        }
    }
}

// export
// module.exports = { range };
export { range };

History

0: (?)

Last updated