diff -r 3ba74350237d -r 32eaba9cf30e svghmi/pythonic.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/svghmi/pythonic.js Wed May 11 12:12:16 2022 +0200 @@ -0,0 +1,206 @@ +/* + +From https://github.com/keyvan-m-sadeghi/pythonic + +Slightly modified in order to be usable in browser (i.e. not as a node.js module) + +The MIT License (MIT) + +Copyright (c) 2016 Assister.Ai + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +class Iterator { + constructor(generator) { + this[Symbol.iterator] = generator; + } + + async * [Symbol.asyncIterator]() { + for (const element of this) { + yield await element; + } + } + + map(callback) { + const result = []; + for (const element of this) { + result.push(callback(element)); + } + + return result; + } + + filter(callback) { + const result = []; + for (const element of this) { + if (callback(element)) { + result.push(element); + } + } + + return result; + } + + reduce(callback, initialValue) { + let empty = typeof initialValue === 'undefined'; + let accumulator = initialValue; + let index = 0; + for (const currentValue of this) { + if (empty) { + accumulator = currentValue; + empty = false; + continue; + } + + accumulator = callback(accumulator, currentValue, index, this); + index++; + } + + if (empty) { + throw new TypeError('Reduce of empty Iterator with no initial value'); + } + + return accumulator; + } + + some(callback) { + for (const element of this) { + if (callback(element)) { + return true; + } + } + + return false; + } + + every(callback) { + for (const element of this) { + if (!callback(element)) { + return false; + } + } + + return true; + } + + static fromIterable(iterable) { + return new Iterator(function * () { + for (const element of iterable) { + yield element; + } + }); + } + + toArray() { + return Array.from(this); + } + + next() { + if (!this.currentInvokedGenerator) { + this.currentInvokedGenerator = this[Symbol.iterator](); + } + + return this.currentInvokedGenerator.next(); + } + + reset() { + delete this.currentInvokedGenerator; + } +} + +function rangeSimple(stop) { + return new Iterator(function * () { + for (let i = 0; i < stop; i++) { + yield i; + } + }); +} + +function rangeOverload(start, stop, step = 1) { + return new Iterator(function * () { + for (let i = start; i < stop; i += step) { + yield i; + } + }); +} + +function range(...args) { + if (args.length < 2) { + return rangeSimple(...args); + } + + return rangeOverload(...args); +} + +function enumerate(iterable) { + return new Iterator(function * () { + let index = 0; + for (const element of iterable) { + yield [index, element]; + index++; + } + }); +} + +const _zip = longest => (...iterables) => { + if (iterables.length < 2) { + throw new TypeError("zip takes 2 iterables at least, "+iterables.length+" given"); + } + + return new Iterator(function * () { + const iterators = iterables.map(iterable => Iterator.fromIterable(iterable)); + while (true) { + const row = iterators.map(iterator => iterator.next()); + const check = longest ? row.every.bind(row) : row.some.bind(row); + if (check(next => next.done)) { + return; + } + + yield row.map(next => next.value); + } + }); +}; + +const zip = _zip(false), zipLongest= _zip(true); + +function items(obj) { + let {keys, get} = obj; + if (obj instanceof Map) { + keys = keys.bind(obj); + get = get.bind(obj); + } else { + keys = function () { + return Object.keys(obj); + }; + + get = function (key) { + return obj[key]; + }; + } + + return new Iterator(function * () { + for (const key of keys()) { + yield [key, get(key)]; + } + }); +} + +/* +module.exports = {Iterator, range, enumerate, zip: _zip(false), zipLongest: _zip(true), items}; +*/