diff --git a/Array.js b/Array.js index 3a4c3c8..9064a5d 100644 --- a/Array.js +++ b/Array.js @@ -250,6 +250,12 @@ Array.prototype.sforEach = wrapIterFunc('forEach') // very long array by interrupting the processing with a timeout... // // XXX should these return a partial result on StopIteration? +// XXX add generators: +// .map(..) / .filter(..) / .reduce(..) +// ...the basis here should be the chunks, i.e. each cycle should +// go through a chunk... +// ...the mixin can be generic, i.e. applicable to Array, and +// other stuff... var makeChunkIter = function(iter, wrapper){ wrapper = wrapper || function(res, func, array, e){ @@ -436,6 +442,17 @@ function(func, ...arrays){ : this.constructor.zip(func, this, ...arrays) } +// +// array.iter() +// -> iterator +// +// +// XXX revise name +Array.prototype.iter = function*(){ + for(var e of this){ + yield e } } + + /********************************************************************** diff --git a/Generator.js b/Generator.js new file mode 100644 index 0000000..5594760 --- /dev/null +++ b/Generator.js @@ -0,0 +1,133 @@ +/********************************************************************** +* +* +* +**********************************************/ /* c8 ignore next 2 */ +((typeof define)[0]=='u'?function(f){module.exports=f(require)}:define) +(function(require){ var module={} // make module AMD/node compatible... +/*********************************************************************/ + + + + +/*********************************************************************/ + +var Generator = +module.Generator = + (function*(){}).__proto__ + + +//--------------------------------------------------------------------- +// Generator "class" methods... +// +// the following are the same: +// 1) Wrapper +// var combined = function(...args){ +// return someGenerator(...args) +// .filter(function(e){ ... }) +// .map(function(e){ ... }) } +// +// combined( .. ) +// +// 2) Static generator methods... +// var combined = someGenerator +// .filter(function(e){ ... }) +// .map(function(e){ ... }) +// +// combined( .. ) +// + +// XXX do a better .toString(..)... +// should be of the format: +// () +// .() +// ... +// XXX this needs to be of the correct type... +var makeGenerator = function(name){ + return function(...args){ + var that = this + return function*(){ + yield* that(...arguments)[name](...args) } } } + + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +Generator.map = makeGenerator('map') +Generator.filter = makeGenerator('filter') +Generator.reduce = makeGenerator('reduce') +Generator.flat = makeGenerator('flat') + +Generator.then = function(...args){ + var that = this + return function(){ + return that(...arguments).then(func) } } + +Generator.toArray = function(){ + var that = this + return function(){ + return that(...arguments).toArray() } } + + + +//--------------------------------------------------------------------- +// Generator instance methods... + +Generator.prototype.map = function*(func){ + var i = 0 + for(var e of this){ + yield func(e, i++, this) } } +Generator.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){ + var i = 0 + for(var e of this){ + res = func(res, e, i++, this) } + yield res } +Generator.prototype.flat = function*(depth=1){ + if(depth == 0){ + return this } + for(var e of this){ + if(e instanceof Array){ + for(var i=0; i < e.length; i++){ + if(depth <= 1){ + yield e[i] + + } else { + yield* typeof(e[i].flat) == 'function' ? + e[i].flat(depth-1) + : e[i] } } + + // XXX the test will not work yet... + } else if(e instanceof Generator){ + if(depth <= 1){ + // XXX should we expand the generaaator here??? + yield [...e] + + } else { + yield* e.flat(depth-1) } + + } else { + yield e } } } + +Generator.prototype.then = function(func){ + var that = this + return new Promise(function(resolve){ + resolve([...that]) }) } + +Generator.prototype.toArray = function(){ + return [...this] } + + +// XXX these are potentially bad because with negative indexes well need +// to run throu the whole iterator and cache the data... +//Generator.prototype.slice = function(from=0, to=-1){ } +//Generator.prototype.reverse = function(){ } + + + + +/********************************************************************** +* vim:set ts=4 sw=4 : */ return module }) diff --git a/Promise.js b/Promise.js index 70b51b6..644aef5 100644 --- a/Promise.js +++ b/Promise.js @@ -156,6 +156,21 @@ object.Constructor('_CooperativePromise', Promise, { +//--------------------------------------------------------------------- +// promise iterators... + +// XXX like Promise.all(..) but creates an iterable promise... +var IterablePromise = +module.IterablePromise = +Promise.iter = +object.Constructor('IterablePromise', Promise, { + map: function(){}, + filter: function(){}, + reduce: function(){}, +}) + + + /********************************************************************** * vim:set ts=4 sw=4 : */ return module }) diff --git a/package.json b/package.json index c9f9f43..c081974 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ig-types", - "version": "3.3.1", + "version": "3.4.0", "description": "Generic JavaScript types and type extensions...", "main": "main.js", "scripts": { diff --git a/runner.js b/runner.js index c340772..2db9fac 100644 --- a/runner.js +++ b/runner.js @@ -160,6 +160,16 @@ module.Queue = object.Constructor('Queue', Array, { queueEmpty: makeEvent(function(func){ return this.on('queueEmpty', ...arguments) }), + // helpers... + // + // XXX how do we reference the tasks here??? + // - indexes + // - ranges -- simelar to .slice(..) + // - by value + // XXX + prioritize: function(){}, + // XXX same as prioritize but adds stuff to the tail... + delay: function(){}, // main runner... //