From 635df6a889fb8bd0bb4dbf1264300ae78f7027ee Mon Sep 17 00:00:00 2001 From: "Alex A. Naanou" Date: Tue, 10 Nov 2020 03:04:04 +0300 Subject: [PATCH] fixes... Signed-off-by: Alex A. Naanou --- Generator.js | 119 ++++++++++++++++++++++++++++++++++++++------------- README.md | 63 +++++++++++++++++++++++++++ package.json | 2 +- 3 files changed, 154 insertions(+), 30 deletions(-) diff --git a/Generator.js b/Generator.js index 8f01c01..f68267e 100644 --- a/Generator.js +++ b/Generator.js @@ -11,14 +11,65 @@ /*********************************************************************/ +// The generator hirearchy in JS is a bit complicated. +// +// Consider the following: +// +// // this is the generator function (i.e. the constructor) +// var Iter = function*(lst){ +// for(var e of lst){ +// yield e }} +// +// // this is the generator instance (constructod instance)... +// var iter = Iter([1,2,3]) +// +// +// In this module we need to add methods to be visible from either Iter +// or iter from the above example, so we need the access the prototypes +// of each of them. +// +// GeneratorPrototype +// is the prototype of the generator construcotrs (i.e. Iter(..) +// from the above example) +// +// GeneratorPrototype.prototype +// is the generator instance prototype (i.e. iter for the above +// code) +// +// +// Also the following applies: +// +// iter instanceof Iter // -> true +// +// Iter instanceof Generator +// +// +// NOTE: there appears no way to test if iter is instnace of some +// generic Generator... +// +//--------------------------------------------------------------------- + +var GeneratorPrototype = + (function*(){}).constructor.prototype + +var Generator = +module.Generator = + (function*(){}).constructor + + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +// generic generator wrapper... +var iter = +module.iter = +function*(lst){ + for(var e of lst){ + yield e } } -var Generator = -module.Generator = - (function*(){}).__proto__ //--------------------------------------------------------------------- -// Generator "class" methods... +// GeneratorPrototype "class" methods... // // the following are the same: // 1) Wrapper @@ -57,31 +108,41 @@ var makePromise = function(name){ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// XXX GeneratorPrototype can't be used as a generator constructor... -// XXX need testing... -Generator.at = makeGenerator('at') -Generator.slice = makeGenerator('slice') -Generator.flat = makeGenerator('flat') -Generator.toArray = function(){ +// XXX should this be a generator??? +GeneratorPrototype.at = makeGenerator('at') +GeneratorPrototype.slice = makeGenerator('slice') +GeneratorPrototype.flat = makeGenerator('flat') +GeneratorPrototype.toArray = function(){ var that = this return function(){ return that(...arguments).toArray() } } +GeneratorPrototype.pop = function(){ + var that = this + return function(){ + return that(...arguments).toArray().pop() } } +GeneratorPrototype.shift = function(){ + var that = this + return function(){ + return that(...arguments).toArray().shift() } } -Generator.map = makeGenerator('map') -Generator.filter = makeGenerator('filter') -Generator.reduce = makeGenerator('reduce') -Generator.flat = makeGenerator('flat') +GeneratorPrototype.map = makeGenerator('map') +GeneratorPrototype.filter = makeGenerator('filter') +GeneratorPrototype.reduce = makeGenerator('reduce') +GeneratorPrototype.flat = makeGenerator('flat') -Generator.then = makePromise('then') -Generator.catch = makePromise('catch') -Generator.finally = makePromise('finally') +GeneratorPrototype.then = makePromise('then') +GeneratorPrototype.catch = makePromise('catch') +GeneratorPrototype.finally = makePromise('finally') //--------------------------------------------------------------------- -// Generator instance methods... +// GeneratorPrototype instance methods... -Generator.prototype.at = function*(i){ +// XXX should this be a generator??? +GeneratorPrototype.prototype.at = function*(i){ // sanity check... if(i < 0){ throw new Error('.at(..): ' @@ -94,7 +155,7 @@ Generator.prototype.at = function*(i){ // NOTE: this is different from Array's .slice(..) in that it does not // support negative indexes -- this is done because there is no way // to judge the length of a generator untill it is fully done... -Generator.prototype.slice = function*(from=0, to=Infity){ +GeneratorPrototype.prototype.slice = function*(from=0, to=Infity){ // sanity check... if(from < 0 || to < 0){ throw new Error('.slice(..): ' @@ -108,7 +169,7 @@ Generator.prototype.slice = function*(from=0, to=Infity){ if(i >= from){ yield e } i++ } }, -Generator.prototype.flat = function*(depth=1){ +GeneratorPrototype.prototype.flat = function*(depth=1){ if(depth == 0){ return this } for(var e of this){ @@ -123,7 +184,7 @@ Generator.prototype.flat = function*(depth=1){ : e[i] } } // XXX the test will not work yet... - } else if(e instanceof Generator){ + } else if(e instanceof GeneratorPrototype){ if(depth <= 1){ // XXX should we expand the generaaator here??? yield [...e] @@ -133,19 +194,19 @@ Generator.prototype.flat = function*(depth=1){ } else { yield e } } } -Generator.prototype.toArray = function(){ +GeneratorPrototype.prototype.toArray = function(){ return [...this] } -Generator.prototype.map = function*(func){ +GeneratorPrototype.prototype.map = function*(func){ var i = 0 for(var e of this){ yield func(e, i++, this) } } -Generator.prototype.filter = function*(func){ +GeneratorPrototype.prototype.filter = function*(func){ var i = 0 for(var e of this){ if(func(e, i++, this)){ yield e } } } -Generator.prototype.reduce = function*(func, res){ +GeneratorPrototype.prototype.reduce = function*(func, res){ var i = 0 for(var e of this){ res = func(res, e, i++, this) } @@ -154,15 +215,15 @@ Generator.prototype.reduce = function*(func, res){ // promise results... // // XXX how do we handle reject(..) / .catch(..)??? -Generator.prototype.promise = function(){ +GeneratorPrototype.prototype.promise = function(){ var that = this return new Promise(function(resolve){ resolve([...that]) }) } -Generator.prototype.then = function(func){ +GeneratorPrototype.prototype.then = function(func){ return this.promise().then(func) } -Generator.prototype.catch = function(func){ +GeneratorPrototype.prototype.catch = function(func){ return this.promise().catch(func) } -Generator.prototype.finally = function(func){ +GeneratorPrototype.prototype.finally = function(func){ return this.promise().finally(func) } diff --git a/README.md b/README.md index fdc7b3c..7ef313f 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ A library of JavaScript type extensions, types and type utilities. - [`.toKeys(..)`](#arraytokeys) - [`.toMap(..)`](#arraytomap) - [`Array.zip(..)` / `.zip(..)`](#arrayzip--arrayzip) + - [`.iter()`](#arrayiter) - [Abortable `Array` iteration](#abortable-array-iteration) - [`array.StopIteration`](#arraystopiteration) - [`.smap(..)` / `.sfilter(..)` / `.sreduce(..)` / `.sforEach(..)`](#arraysmap--arraysfilter--arraysreduce--arraysforeach) @@ -58,6 +59,18 @@ A library of JavaScript type extensions, types and type utilities. - [`RegExp.quoteRegExp(..)`](#regexpquoteregexp) - ['Promise'](#promise) - [`Promise.cooperative(..)`](#promisecooperative) + - [`Generator`](#generator) + - [Generator instance iteration](#generator-instance-iteration) + - [`.map(..)` / `.filter(..)` / `.reduce(..)` / `.flat()`](#generatormap--generatorfilter--generatorreduce--generatorflat) + - [`.promise()`](#generatorpromise) + - [`.then(..)` / `.catch(..)` / `.finally(..)`](#generatorthen--generatorcatch--generatorfinally) + - [`.toArray()`](#generatortoarray) + - [Generator constructor iteration workflow](#generator-constructor-iteration-workflow) + - [`Generator.at(..)`](#generatorat) + - [`Generator.slice(..)`](#generatorslice) + - [`Generator.map(..)` / `Generator.filter(..)` / `Generator.reduce(..)` / `Generator.flat()`](#generatormap--generatorfilter--generatorreduce--generatorflat-1) + - [`Generator.toArray()`](#generatortoarray-1) + - [`Generator.then(..)` / `Generator.catch(..)` / `Generator.finally(..)`](#generatorthen--generatorcatch--generatorfinally-1) - [Containers](#containers) - [`containers.UniqueKeyMap()` (`Map`)](#containersuniquekeymap-map) - [`.set(..)`](#unique-key-mapset) @@ -342,6 +355,12 @@ This will return `true` if: #### `Array.zip(..)` / `.zip(..)` +#### `.iter()` + +Return an iterator/generator from the current array. + +This is useful in combination with the Generator extensions XXX + ### Abortable `Array` iteration @@ -533,12 +552,56 @@ Default value: `50` #### `RegExp.quoteRegExp(..)` + ### 'Promise' #### `Promise.cooperative(..)` +## `Generator` + + +### Generator instance iteration + +#### `.map(..)` / `.filter(..)` / `.reduce(..)` / `.flat()` + +#### `.promise()` + +#### `.then(..)` / `.catch(..)` / `.finally(..)` + +#### `.toArray()` + + +### Generator constructor iteration workflow + +```javascript +var {Generator} = require('ig-types/Generator') + +var sumOdds = Generator + .filter(function(e){ + return e % 2 == 1 }) + .reduce(function(r, e){ + return r + e }, 0) + .pop() + +console.log(sumOdds([1, 2, 3, 4, 5, 6, 7])) // -> 16 + +``` + +### `Generator.at(..)` + +### `Generator.slice(..)` + +This is like `Array`'s `.slice(..)` but does not support negative indexes. + +### `Generator.map(..)` / `Generator.filter(..)` / `Generator.reduce(..)` / `Generator.flat()` + +### `Generator.toArray()` + +### `Generator.then(..)` / `Generator.catch(..)` / `Generator.finally(..)` + + ## Containers ```javascript diff --git a/package.json b/package.json index 269d65f..2ba2c13 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ig-types", - "version": "3.4.2", + "version": "3.4.3", "description": "Generic JavaScript types and type extensions...", "main": "main.js", "scripts": {