From c804028d9fe0f331f940ed2b948f784fbe37f399 Mon Sep 17 00:00:00 2001 From: "Alex A. Naanou" Date: Thu, 23 Jun 2022 13:37:46 +0300 Subject: [PATCH] more work on te generic .iter(..) (Array.js is not done yet) + docs... Signed-off-by: Alex A. Naanou --- Array.js | 1 + README.md | 23 +++++++++++++++++--- generator.js | 60 +++++++++++++++++++++++++++++++++++++++++++--------- package.json | 2 +- 4 files changed, 72 insertions(+), 14 deletions(-) diff --git a/Array.js b/Array.js index f49543e..f25f787 100644 --- a/Array.js +++ b/Array.js @@ -212,6 +212,7 @@ object.Mixin('ArrayMixin', 'soft', { // done... : [] }, + // XXX add handler function support -- a-la generator.js' iter: function*(lst=[]){ yield* lst.iter() }, }) diff --git a/README.md b/README.md index 69b9a26..09a6f49 100644 --- a/README.md +++ b/README.md @@ -94,7 +94,7 @@ Library of JavaScript type extensions, types and utilities. - [`generator.iter(..)`](#generatoriter) - [`generator.STOP`](#generatorstop) - [Generator instance iteration](#generator-instance-iteration) - - [`.iter()`](#generatoriter-1) + - [`.iter(..)`](#generatoriter-1) - [`.map(..)` / `.filter(..)`](#generatormap--generatorfilter) - [`.reduce(..)` / `.greduce(..)`](#generatorreduce--generatorgreduce) - [`.slice(..)`](#generatorslice) @@ -2031,7 +2031,7 @@ Chained generators handle items depth-first, i.e. the items are passed as they are yielded down the generator chain. -#### `.iter()` +#### `.iter(..)` Iterate over the generator. ```bnf @@ -2039,7 +2039,24 @@ Iterate over the generator. -> ``` -This is here mainly for compatibility with [``'s `.iter()`](#arrayiter--arrayiter). +XXX move this to `generator.iter(..)` + +Compatible with [``'s `.iter()`](#arrayiter--arrayiter). + +`.iter(..)` also supports a handler function +```bnf +.iter() + -> + + +(, ) + -> + -> [, ..] + -> [] +``` + +Note that the iterables returned by `(..)` will be expanded, to prevent +this wrap them in an array. #### `.map(..)` / `.filter(..)` diff --git a/generator.js b/generator.js index 26e3220..38c4d26 100644 --- a/generator.js +++ b/generator.js @@ -85,14 +85,38 @@ var ITERATOR_PROTOTYPES = [ //--------------------------------------------------------------------- - // generic generator wrapper... + +// helper... +var __iter = +module.__iter = +function*(lst=[]){ + if(typeof(lst) == 'object' && Symbol.iterator in lst){ + yield* lst + } else { + yield lst } } + +// XXX updatae Array.js' version for compatibility... +// XXX DOCS!!! var iter = module.iter = Generator.iter = - function*(lst=[]){ - for(var e of lst){ - yield e } } + function(lst=[]){ + // handler -> generator-constructor... + if(typeof(lst) == 'function'){ + // we need to be callable... + var that = this instanceof Function ? + this + // generic root generator... + : module.__iter + return function*(){ + yield* that(...arguments).iter(lst) } } + // no handler -> generator instance... + return module.__iter(lst) } + +// NOTE: we need .iter(..) to both return generators if passed an iterable +// and genereator constructos if passed a function... +iter.__proto__ = GeneratorPrototype @@ -229,9 +253,7 @@ module.GeneratorMixin = object.Mixin('GeneratorMixin', 'soft', { STOP: object.STOP, - // NOTE: this is here for compatibility with Array.iter(..) - iter: function*(lst=[]){ - yield* module.iter(lst) }, + iter: module.iter, gat: makeGenerator('gat'), at: function(i){ @@ -309,9 +331,23 @@ object.Mixin('GeneratorMixin', 'soft', { var GeneratorProtoMixin = module.GeneratorProtoMixin = object.Mixin('GeneratorProtoMixin', 'soft', { - // NOTE: this is here for compatibility with [..].iter() - iter: function*(){ - yield* this }, + // XXX use module.iter(..) ??? + iter: function*(handler){ + if(handler){ + var i = 0 + for(var elem of this){ + var res = handler.call(this, elem, i) + // expand iterables... + if(typeof(res) == 'object' + && Symbol.iterator in res){ + yield* res + // as-is... + } else { + yield res }} + // no handler... + } else { + yield* this } }, + //*/ at: function(i){ return this.gat(i).next().value }, @@ -477,6 +513,7 @@ module.AsyncGeneratorMixin = object.Mixin('AsyncGeneratorMixin', 'soft', { // XXX TEST... iter: makeGenerator('async', 'iter'), + map: makeGenerator('async', 'map'), filter: makeGenerator('async', 'filter'), reduce: makeGenerator('async', 'reduce'), @@ -522,6 +559,9 @@ object.Mixin('AsyncGeneratorProtoMixin', 'soft', { return func.call(this, elem, i) ? [elem] : [] }) }, + // NOTE: there is not much point in .reduceRight(..) in an async + // generator as we'll need to fully unwind it then go from the + // end... reduce: async function(func, state){ this.iter(function(elem, i){ state = func.call(this, state, elem, i) diff --git a/package.json b/package.json index eddb9af..b3bbc8b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ig-types", - "version": "6.15.1", + "version": "6.15.5", "description": "Generic JavaScript types and type extensions...", "main": "main.js", "scripts": {