2020-10-07 03:53:10 +03:00
|
|
|
# types.js
|
|
|
|
|
|
|
|
|
|
A library of JavaScript type extensions, types and type utilities.
|
|
|
|
|
|
|
|
|
|
- [types.js](#typesjs)
|
2020-10-07 07:33:58 +03:00
|
|
|
- [Installation](#installation)
|
|
|
|
|
- [Basic usage](#basic-usage)
|
2020-11-18 06:09:43 +03:00
|
|
|
- [`Object`](#object)
|
|
|
|
|
- [`Object.deepKeys(..)`](#objectdeepkeys)
|
|
|
|
|
- [`Object.copy(..)` (EXPERIMENTAL)](#objectcopy-experimental)
|
|
|
|
|
- [`Object.flatCopy(..)`](#objectflatcopy)
|
|
|
|
|
- [`Object.match(..)`](#objectmatch)
|
|
|
|
|
- [`Object.matchPartial(..)`](#objectmatchpartial)
|
|
|
|
|
- [`<object>.run(..)`](#objectrun)
|
|
|
|
|
- [`Object.sort(..)`](#objectsort)
|
|
|
|
|
- [`Array`](#array)
|
|
|
|
|
- [`<array>.first(..)` / `<array>.last(..)`](#arrayfirst--arraylast)
|
|
|
|
|
- [`<array>.rol(..)`](#arrayrol)
|
|
|
|
|
- [`<array>.compact()`](#arraycompact)
|
|
|
|
|
- [`<array>.len`](#arraylen)
|
2020-12-08 01:53:40 +03:00
|
|
|
- [`<array>.unique()` / `<array>.tailUnique()`](#arrayunique--arraytailunique)
|
|
|
|
|
- [`<array>.trim()` / `<array>.trimStart()` / `<array>.trimEnd()`](#arraytrim--arraytrimstart--arraytrimend)
|
2020-11-18 06:09:43 +03:00
|
|
|
- [`<array>.cmp(..)`](#arraycmp)
|
|
|
|
|
- [`<array>.setCmp(..)`](#arraysetcmp)
|
|
|
|
|
- [`<array>.sortAs(..)`](#arraysortas)
|
|
|
|
|
- [`<array>.inplaceSortAs(..)`](#arrayinplacesortas)
|
|
|
|
|
- [`<array>.toKeys(..)`](#arraytokeys)
|
|
|
|
|
- [`<array>.toMap(..)`](#arraytomap)
|
|
|
|
|
- [`Array.zip(..)` / `<array>.zip(..)`](#arrayzip--arrayzip)
|
2020-11-18 06:59:56 +03:00
|
|
|
- [`Array.iter(..)` / `<array>.iter()`](#arrayiter--arrayiter)
|
2020-11-07 03:19:52 +03:00
|
|
|
- [Abortable `Array` iteration](#abortable-array-iteration)
|
2020-11-23 22:27:30 +03:00
|
|
|
- [`array.STOP` / `array.STOP(..)`](#arraystop--arraystop)
|
2020-11-07 03:19:52 +03:00
|
|
|
- [`<array>.smap(..)` / `<array>.sfilter(..)` / `<array>.sreduce(..)` / `<array>.sforEach(..)`](#arraysmap--arraysfilter--arraysreduce--arraysforeach)
|
2020-10-11 03:09:48 +03:00
|
|
|
- [Large `Array` iteration (chunked)](#large-array-iteration-chunked)
|
2020-11-23 22:27:30 +03:00
|
|
|
- [`array.STOP` / `array.STOP(..)`](#arraystop--arraystop-1)
|
2020-10-11 03:09:48 +03:00
|
|
|
- [`<array>.CHUNK_SIZE`](#arraychunk_size)
|
2020-12-08 01:53:40 +03:00
|
|
|
- [`<array>.mapChunks(..)` / `<array>.filterChunks(..)` / `<array>.reduceChunks(..)`](#arraymapchunks--arrayfilterchunks--arrayreducechunks)
|
2020-11-18 06:09:43 +03:00
|
|
|
- [`Map`](#map)
|
|
|
|
|
- [`<map>.sort(..)`](#mapsort)
|
|
|
|
|
- [`Set`](#set)
|
|
|
|
|
- [`<set>.unite(..)`](#setunite)
|
|
|
|
|
- [`<set>.intersect(..)`](#setintersect)
|
|
|
|
|
- [`<set>.subtract(..)`](#setsubtract)
|
|
|
|
|
- [`<set>.sort(..)`](#setsort)
|
|
|
|
|
- [`Date`](#date)
|
|
|
|
|
- [`Date.timeStamp(..)`](#datetimestamp)
|
|
|
|
|
- [`Date.fromTimeStamp(..)`](#datefromtimestamp)
|
|
|
|
|
- [`Date.str2ms(..)`](#datestr2ms)
|
|
|
|
|
- [`<date>.toShortDate(..)`](#datetoshortdate)
|
|
|
|
|
- [`<date>.getTimeStamp(..)`](#dategettimestamp)
|
|
|
|
|
- [`<date>.setTimeStamp(..)`](#datesettimestamp)
|
|
|
|
|
- [`String`](#string)
|
|
|
|
|
- [`<string>.capitalize()`](#stringcapitalize)
|
2020-12-17 18:55:28 +03:00
|
|
|
- [`<string>.indent(..)`](#stringindent)
|
2020-11-18 06:09:43 +03:00
|
|
|
- [`RegExp`](#regexp)
|
|
|
|
|
- [`RegExp.quoteRegExp(..)`](#regexpquoteregexp)
|
|
|
|
|
- [`Promise`](#promise)
|
|
|
|
|
- [Cooperative promises](#cooperative-promises)
|
2020-11-03 05:22:29 +03:00
|
|
|
- [`Promise.cooperative(..)`](#promisecooperative)
|
2020-11-18 06:09:43 +03:00
|
|
|
- [`<promise-coop>.set(..)`](#promise-coopset)
|
|
|
|
|
- [`<promise-coop>.isSet`](#promise-coopisset)
|
|
|
|
|
- [Promise iteration](#promise-iteration)
|
|
|
|
|
- [`Promise.iter(..)` / `promise.IterablePromise(..)`](#promiseiter--promiseiterablepromise)
|
|
|
|
|
- [`<promise-iter>.map(..)` / `<promise-iter>.filter(..)` / `<promise-iter>.reduce(..)`](#promise-itermap--promise-iterfilter--promise-iterreduce)
|
|
|
|
|
- [`<promise-iter>.flat(..)`](#promise-iterflat)
|
|
|
|
|
- [`<promise-iter>.then(..)` / `<promise-iter>.catch(..)` / `<promise-iter>.finally(..)`](#promise-iterthen--promise-itercatch--promise-iterfinally)
|
|
|
|
|
- [Advanced handler](#advanced-handler)
|
2020-11-10 03:25:00 +03:00
|
|
|
- [Generator extensions and utilities](#generator-extensions-and-utilities)
|
|
|
|
|
- [The basics](#the-basics)
|
2021-03-24 18:57:02 +03:00
|
|
|
- [`generator.Generator`](#generatorgenerator)
|
2020-11-10 03:25:00 +03:00
|
|
|
- [`generator.iter(..)`](#generatoriter)
|
2020-11-10 03:04:04 +03:00
|
|
|
- [Generator instance iteration](#generator-instance-iteration)
|
2021-03-25 02:59:15 +03:00
|
|
|
- [`<generator>.map(..)` / `<generator>.filter(..)` / `<generator>.reduce(..)`](#generatormap--generatorfilter--generatorreduce)
|
|
|
|
|
- [`<generator>.slice(..)`](#generatorslice)
|
|
|
|
|
- [`<generator>.at(..)`](#generatorat)
|
|
|
|
|
- [`<generator>.flat(..)`](#generatorflat)
|
|
|
|
|
- [`<generator>.shift()` / `<generator>.pop()`](#generatorshift--generatorpop)
|
2020-11-10 03:04:04 +03:00
|
|
|
- [`<generator>.promise()`](#generatorpromise)
|
|
|
|
|
- [`<generator>.then(..)` / `<generator>.catch(..)` / `<generator>.finally(..)`](#generatorthen--generatorcatch--generatorfinally)
|
|
|
|
|
- [`<generator>.toArray()`](#generatortoarray)
|
2020-11-18 06:59:56 +03:00
|
|
|
- [Generator constructor iteration](#generator-constructor-iteration)
|
2021-03-25 02:59:15 +03:00
|
|
|
- [`<Generator>.at(..)`](#generatorat-1)
|
|
|
|
|
- [`<Generator>.shift()` / `<Generator>.pop()`](#generatorshift--generatorpop-1)
|
|
|
|
|
- [`<Generator>.slice(..)`](#generatorslice-1)
|
|
|
|
|
- [`<Generator>.map(..)` / `<Generator>.filter(..)` / `<Generator>.reduce(..)` / `<Generator>.flat()`](#generatormap--generatorfilter--generatorreduce--generatorflat)
|
2021-03-24 18:57:02 +03:00
|
|
|
- [`<Generator>.toArray()`](#generatortoarray-1)
|
|
|
|
|
- [`<Generator>.then(..)` / `<Generator>.catch(..)` / `<Generator>.finally(..)`](#generatorthen--generatorcatch--generatorfinally-1)
|
2020-10-07 03:53:10 +03:00
|
|
|
- [Containers](#containers)
|
2020-10-07 07:33:58 +03:00
|
|
|
- [`containers.UniqueKeyMap()` (`Map`)](#containersuniquekeymap-map)
|
2020-10-07 14:48:47 +03:00
|
|
|
- [`<unique-key-map>.set(..)`](#unique-key-mapset)
|
2020-10-07 03:53:10 +03:00
|
|
|
- [`<unique-key-map>.reset(..)`](#unique-key-mapreset)
|
|
|
|
|
- [`<unique-key-map>.rename(..)`](#unique-key-maprename)
|
2020-10-07 15:09:36 +03:00
|
|
|
- [`<unique-key-map>.orderedRename(..)`](#unique-key-maporderedrename)
|
2020-10-07 14:48:47 +03:00
|
|
|
- [`<unique-key-map>.unorderedRename(..)`](#unique-key-mapunorderedrename)
|
2020-10-07 03:53:10 +03:00
|
|
|
- [`<unique-key-map>.keysOf(..)`](#unique-key-mapkeysof)
|
2020-10-07 14:48:47 +03:00
|
|
|
- [`<unique-key-map>.originalKey(..)`](#unique-key-maporiginalkey)
|
|
|
|
|
- [`<unique-key-map>.uniqueKey(..)`](#unique-key-mapuniquekey)
|
2020-10-07 07:33:58 +03:00
|
|
|
- [`<unique-key-map>.__key_pattern__`](#unique-key-map__key_pattern__)
|
2020-10-07 15:09:36 +03:00
|
|
|
- [`<unique-key-map>.__unordered_rename__`](#unique-key-map__unordered_rename__)
|
2020-11-15 05:13:35 +03:00
|
|
|
- [Event](#event)
|
|
|
|
|
- [`event.Eventfull(..)`](#eventeventfull)
|
|
|
|
|
- [`event.Event(..)`](#eventevent)
|
2020-11-16 02:38:19 +03:00
|
|
|
- [`event.TRIGGER`](#eventtrigger)
|
2020-11-15 05:13:35 +03:00
|
|
|
- [`event.EventHandlerMixin`](#eventeventhandlermixin)
|
|
|
|
|
- [`<obj>.on(..)`](#objon)
|
|
|
|
|
- [`<obj>.one(..)`](#objone)
|
|
|
|
|
- [`<obj>.off(..)`](#objoff)
|
|
|
|
|
- [`<obj>.trigger(..)`](#objtrigger)
|
|
|
|
|
- [`event.EventDocMixin`](#eventeventdocmixin)
|
|
|
|
|
- [`<obj>.eventfull`](#objeventfull)
|
|
|
|
|
- [`<obj>.events`](#objevents)
|
|
|
|
|
- [`event.EventMixin`](#eventeventmixin)
|
2020-11-07 03:19:52 +03:00
|
|
|
- [Runner](#runner)
|
2020-11-28 03:47:31 +03:00
|
|
|
- [Micro task queue](#micro-task-queue)
|
2020-12-17 18:55:28 +03:00
|
|
|
- [`STOP`](#stop)
|
|
|
|
|
- [`SKIP`](#skip)
|
2020-12-08 01:53:40 +03:00
|
|
|
- [`Queue(..)` / `Queue.runTasks(..)`](#queue--queueruntasks)
|
|
|
|
|
- [`Queue.handle(..)`](#queuehandle)
|
2020-11-07 03:19:52 +03:00
|
|
|
- [`<queue>.state`](#queuestate)
|
|
|
|
|
- [`<queue>.start(..)`](#queuestart)
|
2020-12-08 01:53:40 +03:00
|
|
|
- [`<queue>.stop(..)`](#queuestop)
|
|
|
|
|
- [`<queue>.runTask(..)`](#queueruntask)
|
|
|
|
|
- [`<queue>.tasksAdded(..)` (event)](#queuetasksadded-event)
|
|
|
|
|
- [`<queue>.taskStarting(..)` (event)](#queuetaskstarting-event)
|
|
|
|
|
- [`<queue>.taskFailed(..)` (event)](#queuetaskfailed-event)
|
2020-11-07 03:19:52 +03:00
|
|
|
- [`<queue>.taskCompleted(..)` (event)](#queuetaskcompleted-event)
|
2020-12-08 01:53:40 +03:00
|
|
|
- [`<queue>.queueEmpty(..)` (event)](#queuequeueempty-event)
|
2020-12-17 18:55:28 +03:00
|
|
|
- [`<queue>.prioritize(..)`](#queueprioritize)
|
|
|
|
|
- [`<queue>.delay(..)`](#queuedelay)
|
|
|
|
|
- [`<queue>.add(..)`](#queueadd)
|
|
|
|
|
- [`<queue>.clear(..)`](#queueclear)
|
|
|
|
|
- [`FinalizableQueue(..)` / `FinalizableQueue.runTasks(..)` (Queue)](#finalizablequeue--finalizablequeueruntasks-queue)
|
|
|
|
|
- [`<finalizable-queue>.done(..)` (event/method)](#finalizable-queuedone-eventmethod)
|
|
|
|
|
- [`<finalizable-queue>.abort(..)` (event/method)](#finalizable-queueabort-eventmethod)
|
|
|
|
|
- [`<finalizable-queue>.promise(..)`](#finalizable-queuepromise)
|
|
|
|
|
- [`<finalizable-queue>.then(..)`](#finalizable-queuethen)
|
|
|
|
|
- [`<finalizable-queue>.catch(..)`](#finalizable-queuecatch)
|
2020-11-28 03:47:31 +03:00
|
|
|
- [Large task management](#large-task-management)
|
|
|
|
|
- [`runner.TaskManager(..)`](#runnertaskmanager)
|
|
|
|
|
- [`<task-manager>.Task(..)`](#task-managertask)
|
|
|
|
|
- [`<task-manager>.sync_start`](#task-managersync_start)
|
|
|
|
|
- [`<task-manager>.record_times`](#task-managerrecord_times)
|
|
|
|
|
- [`<task-manager>.titled(..)`](#task-managertitled)
|
|
|
|
|
- [`<task-manager>.send(..)`](#task-managersend)
|
|
|
|
|
- [`<task-manager>.stop(..)`](#task-managerstop)
|
|
|
|
|
- [`<task-manager>.done(..)` (event)](#task-managerdone-event)
|
|
|
|
|
- [`<task-manager>.error(..)` (event)](#task-managererror-event)
|
|
|
|
|
- [`<task-manager>.tasksDone(..)` (event)](#task-managertasksdone-event)
|
|
|
|
|
- [`runner.TaskTicket(..)`](#runnertaskticket)
|
|
|
|
|
- [`runner.TaskMixin(..)`](#runnertaskmixin)
|
2020-10-07 07:33:58 +03:00
|
|
|
- [License](#license)
|
2020-10-07 03:53:10 +03:00
|
|
|
|
2020-10-07 07:33:58 +03:00
|
|
|
## Installation
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
$ npm install -s 'ig-types'
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Basic usage
|
|
|
|
|
|
|
|
|
|
To extend everything:
|
|
|
|
|
```javascript
|
|
|
|
|
require('ig-types')
|
|
|
|
|
```
|
|
|
|
|
|
2020-10-09 23:20:00 +03:00
|
|
|
To have access to additional library types and utilities:
|
2020-10-07 07:33:58 +03:00
|
|
|
```javascript
|
|
|
|
|
var types = require('ig-types')
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
`types.js` is organized so as to be able to import/extend only specific
|
|
|
|
|
sub-modules mostly independently so...
|
|
|
|
|
|
2020-10-09 23:20:00 +03:00
|
|
|
In case there is a need to only extend a specific constructor just import
|
|
|
|
|
the module dealing with that constructor (`Array` in this case):
|
2020-10-07 07:33:58 +03:00
|
|
|
```javascript
|
|
|
|
|
// require `ig-types/<constructor-name>`...
|
|
|
|
|
require('ig-types/Array')
|
|
|
|
|
```
|
2021-03-24 02:10:55 +03:00
|
|
|
Note that type patching modules are _mostly_ independent.
|
2020-10-07 07:33:58 +03:00
|
|
|
|
|
|
|
|
And to import specific library modules only:
|
|
|
|
|
```javascript
|
|
|
|
|
var containers = require('ig-types/containers')
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
## `Object`
|
2020-10-07 03:53:10 +03:00
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
```javascript
|
|
|
|
|
require('ig-types/Object')
|
|
|
|
|
```
|
2020-10-07 03:53:10 +03:00
|
|
|
|
2021-03-24 02:10:55 +03:00
|
|
|
Note that this module imports from
|
|
|
|
|
[`object.js`](https://github.com/flynx/object.js) and
|
|
|
|
|
[`object-run.js`](https://github.com/flynx/object-run.js),
|
|
|
|
|
see those modules for more details.
|
|
|
|
|
|
|
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
### `Object.deepKeys(..)`
|
2020-10-07 03:53:10 +03:00
|
|
|
|
2021-03-24 02:10:55 +03:00
|
|
|
Get list of keys from all objects in the prototype chain.
|
2020-12-08 01:53:40 +03:00
|
|
|
```bnf
|
2020-10-09 23:20:00 +03:00
|
|
|
Object.deepKeys(<obj>)
|
2020-12-08 01:53:40 +03:00
|
|
|
-> <keys>
|
2020-10-09 23:20:00 +03:00
|
|
|
```
|
2020-10-07 03:53:10 +03:00
|
|
|
|
2020-10-09 23:20:00 +03:00
|
|
|
This is different from `Object.keys(..)` which only gets _own_ keys from the
|
|
|
|
|
current object.
|
|
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
```javascript
|
|
|
|
|
var a = { x: 123 }
|
|
|
|
|
var b = Object.create(a)
|
|
|
|
|
b.y = 321
|
|
|
|
|
|
|
|
|
|
// get own keys of b...
|
|
|
|
|
Object.keys(b) // -> ['y']
|
|
|
|
|
|
|
|
|
|
// get all keys accessible from b...
|
|
|
|
|
Object.deepKeys(b) // -> ['x', 'y']
|
|
|
|
|
```
|
|
|
|
|
|
2021-03-24 02:10:55 +03:00
|
|
|
For more details see:
|
|
|
|
|
https://github.com/flynx/object.js#deepkeys
|
|
|
|
|
|
|
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
### `Object.copy(..)` (EXPERIMENTAL)
|
2020-10-10 06:27:51 +03:00
|
|
|
|
2021-03-24 02:10:55 +03:00
|
|
|
Create a copy of `<obj>`
|
2020-12-08 01:53:40 +03:00
|
|
|
```bnf
|
2020-10-10 06:27:51 +03:00
|
|
|
Object.copy(<obj>)
|
2020-12-08 01:53:40 +03:00
|
|
|
-> <obj-copy>
|
2020-10-10 06:27:51 +03:00
|
|
|
|
2021-03-24 02:10:55 +03:00
|
|
|
Object.copy(<obj>, <constructor>)
|
|
|
|
|
-> <obj-copy>
|
|
|
|
|
```
|
2020-10-10 06:27:51 +03:00
|
|
|
|
|
|
|
|
This will:
|
|
|
|
|
- create a blank `<obj-copy>`
|
|
|
|
|
- link `<obj-copy>` to the same prototype chain
|
2021-03-24 02:10:55 +03:00
|
|
|
- assign all _own_ keys from `<obj>` to `<obj-copy>`
|
|
|
|
|
|
|
|
|
|
This is similar to `Object.clone(..)` but instead of creating a new descendant of
|
|
|
|
|
the input object with no data this will instead create a new sibling with a copy
|
|
|
|
|
of the instance data.
|
|
|
|
|
|
|
|
|
|
`<constructor>` if given is called to create the instance to be populated,
|
|
|
|
|
otherwise `Object.create(<obj>)` is used.
|
2020-10-10 06:27:51 +03:00
|
|
|
|
2021-03-24 02:10:55 +03:00
|
|
|
Note that `.assign(..)` is used to copy data, thus properties will be copied as values, to copy instance properties use `object.js`'s
|
|
|
|
|
[`.mixinFlat(..)`](https://github.com/flynx/object.js#mixinflat).
|
2020-10-10 06:27:51 +03:00
|
|
|
|
2021-03-24 02:10:55 +03:00
|
|
|
Note that this will make no attempt to clone object type, a `<constructor>`
|
|
|
|
|
should be passed manually if any instance type other that `Object` is required.
|
2020-10-10 06:27:51 +03:00
|
|
|
|
2020-10-07 03:53:10 +03:00
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
### `Object.flatCopy(..)`
|
2020-10-07 03:53:10 +03:00
|
|
|
|
2021-03-24 02:10:55 +03:00
|
|
|
Copy all attributes from the prototype chain of `<obj>` into `<new-obj>`.
|
2020-12-08 01:53:40 +03:00
|
|
|
```bnf
|
2020-10-10 06:27:51 +03:00
|
|
|
Object.flatCopy(<obj>)
|
2020-12-08 01:53:40 +03:00
|
|
|
-> <new-obj>
|
2021-03-24 02:10:55 +03:00
|
|
|
|
|
|
|
|
Object.flatCopy(<obj>, <constructor>)
|
|
|
|
|
-> <new-obj>
|
2020-10-10 06:27:51 +03:00
|
|
|
```
|
|
|
|
|
|
2021-03-24 02:10:55 +03:00
|
|
|
This is different to [`.copy(..)`](#objectcopy-experimental) in that if
|
|
|
|
|
no `<constructor>` is given `<new-obj>` will _not_ be linked into the
|
|
|
|
|
prototype chain of `<obj>`, if this behavior is desired use `o => Object.create(o)`
|
|
|
|
|
as the `<constructor>`.
|
2020-10-10 06:27:51 +03:00
|
|
|
|
|
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
### `Object.match(..)`
|
2020-10-09 23:20:00 +03:00
|
|
|
|
2021-03-24 02:10:55 +03:00
|
|
|
Attribute/value match two objects (non-recursive).
|
|
|
|
|
```bnf
|
|
|
|
|
Object.match(<object>, <other>)
|
|
|
|
|
-> <bool>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Objects `A` and `B` match iff:
|
|
|
|
|
- `A` and `B` are _identical_, i.e. `A === B`
|
|
|
|
|
|
|
|
|
|
or
|
|
|
|
|
- `typeof A == typeof B` _and_,
|
|
|
|
|
- `A` and `B` have the same number of attributes _and_,
|
|
|
|
|
- attribute names match _and_,
|
|
|
|
|
- attribute values are _identical_.
|
|
|
|
|
|
|
|
|
|
And for a less strict match:
|
|
|
|
|
```bnf
|
|
|
|
|
Object.match(<object>, <other>, true)
|
|
|
|
|
-> <bool>
|
|
|
|
|
```
|
|
|
|
|
Like the default case but uses _equality_ instead of _identity_ to match values.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
For more details see:
|
|
|
|
|
https://github.com/flynx/object.js#match
|
|
|
|
|
|
|
|
|
|
<!--
|
|
|
|
|
XXX should this test based on equality or on identity by default???
|
|
|
|
|
...see: Array.cmp(..)
|
|
|
|
|
-->
|
|
|
|
|
|
|
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
### `Object.matchPartial(..)`
|
2020-10-09 23:20:00 +03:00
|
|
|
|
2021-03-24 02:10:55 +03:00
|
|
|
```bnf
|
|
|
|
|
Object.matchPartial(<object>, <other>)
|
|
|
|
|
-> <bool>
|
|
|
|
|
|
|
|
|
|
Object.matchPartial(<object>, <other>, true)
|
|
|
|
|
-> <bool>
|
|
|
|
|
```
|
|
|
|
|
Like `.match(..)` but will check for a _partial_ match, i.e. when `<other>` is a non-strict subset of `<object>`.
|
|
|
|
|
|
|
|
|
|
For more details see:
|
|
|
|
|
https://github.com/flynx/object.js#matchpartial
|
|
|
|
|
|
|
|
|
|
<!--
|
|
|
|
|
XXX should this test based on equality or on identity by default???
|
|
|
|
|
...see: Array.cmp(..)
|
|
|
|
|
-->
|
|
|
|
|
|
|
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
### `<object>.run(..)`
|
2020-10-07 03:53:10 +03:00
|
|
|
|
2020-12-08 01:53:40 +03:00
|
|
|
```bnf
|
2020-10-07 07:33:58 +03:00
|
|
|
<object>.run(<func>)
|
|
|
|
|
-> <object>
|
|
|
|
|
-> <other>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Run a function in the context of `<object>` returning either `<object>`
|
|
|
|
|
itself (if returning `undefined`) or the result.
|
|
|
|
|
|
|
|
|
|
Note that this is accessible from all JavaScript non-primitive objects,
|
|
|
|
|
i.e. everything that inherits from `Object`.
|
|
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
```javascript
|
|
|
|
|
var L = [1, 2, 3]
|
|
|
|
|
.map(function(e){
|
|
|
|
|
return e * 2 })
|
|
|
|
|
// see if the first element is 1 and prepend 1 if it is not...
|
|
|
|
|
.run(function(){
|
|
|
|
|
if(this[0] != 1){
|
|
|
|
|
this.unshift(1) } })
|
|
|
|
|
|
|
|
|
|
console.log(L) // -> [1, 2, 6, 8]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
`.run(..)` is also available standalone via:
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
$ npm install -s object-run
|
|
|
|
|
```
|
|
|
|
|
|
2021-03-24 02:10:55 +03:00
|
|
|
For more details see:
|
2020-10-07 07:33:58 +03:00
|
|
|
https://github.com/flynx/object-run.js
|
|
|
|
|
|
2020-10-07 03:53:10 +03:00
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
### `Object.sort(..)`
|
2020-10-07 16:46:59 +03:00
|
|
|
|
2021-03-24 02:10:55 +03:00
|
|
|
Sort `<obj>` attributes (similar to `Array`'s `.sort(..)`)
|
2020-12-08 01:53:40 +03:00
|
|
|
```bnf
|
2020-10-10 06:27:51 +03:00
|
|
|
Object.sort(<obj>)
|
2020-12-08 01:53:40 +03:00
|
|
|
-> <obj>
|
2020-10-10 06:27:51 +03:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Sort `<obj>` attributes via `<cmp>` function.
|
|
|
|
|
```
|
|
|
|
|
Object.sort(<obj>, <cmp>)
|
2020-12-08 01:53:40 +03:00
|
|
|
-> <obj>
|
2020-10-10 06:27:51 +03:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Sort `<obj>` attributes to the same order of `<order-list>`.
|
2020-12-08 01:53:40 +03:00
|
|
|
```bnf
|
2020-10-10 06:27:51 +03:00
|
|
|
Object.sort(<obj>, <order-list>)
|
2020-12-08 01:53:40 +03:00
|
|
|
-> <obj>
|
2020-10-10 06:27:51 +03:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Note that this rewrites all the keys of `<obj>` thus for very large
|
|
|
|
|
sets of keys/attributes this may be quite expensive.
|
|
|
|
|
|
|
|
|
|
Note that some keys of `Object` may misbehave in JavaScript, currently keys
|
|
|
|
|
that are string values of numbers are sorted automatically by _number value_
|
|
|
|
|
and are not affected by `.sort(..)`, this affects both _Chrome_ and _Firefox_.
|
|
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
```javascript
|
|
|
|
|
var o = {x: 0, a: 1, '100':2, '0':3, ' 27 ':4, b:5}
|
|
|
|
|
|
|
|
|
|
// notice that the order is already different to the order of attributes above...
|
|
|
|
|
Object.keys(o)
|
|
|
|
|
// -> ['0', '100', 'x', 'a', ' 27 ', 'b']
|
|
|
|
|
|
|
|
|
|
// '0' and '100' are not affected by .sort(..) while ' 27 ' is...
|
|
|
|
|
Object.keys(Object.sort(o, ['x', 'a', '100']))
|
|
|
|
|
// -> [ '0', '100', 'x', 'a', ' 27 ', 'b' ]
|
|
|
|
|
```
|
|
|
|
|
|
2020-10-07 16:46:59 +03:00
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
## `Array`
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
require('ig-types/Array')
|
|
|
|
|
```
|
|
|
|
|
or
|
|
|
|
|
```javascript
|
|
|
|
|
var array = require('ig-types/Array')
|
|
|
|
|
```
|
2020-10-07 03:53:10 +03:00
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
### `<array>.first(..)` / `<array>.last(..)`
|
2020-10-07 03:53:10 +03:00
|
|
|
|
2020-10-07 16:46:59 +03:00
|
|
|
Get the first/last items of `<array>`.
|
2020-12-08 01:53:40 +03:00
|
|
|
```bnf
|
2020-10-07 16:46:59 +03:00
|
|
|
<array>.first()
|
2020-12-08 01:53:40 +03:00
|
|
|
-> <item>
|
2020-10-07 16:46:59 +03:00
|
|
|
|
|
|
|
|
<array>.last()
|
2020-12-08 01:53:40 +03:00
|
|
|
-> <item>
|
2020-10-07 16:46:59 +03:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Set the first/last items of `<array>`.
|
2020-12-08 01:53:40 +03:00
|
|
|
```bnf
|
2020-10-07 16:46:59 +03:00
|
|
|
<array>.first(<item>)
|
|
|
|
|
-> <array>
|
|
|
|
|
|
|
|
|
|
<array>.last(<item>)
|
|
|
|
|
-> <array>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Note that these do not affect `<array>` length unless setting items on
|
|
|
|
|
an empty `<array>`.
|
2020-10-07 03:53:10 +03:00
|
|
|
|
|
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
### `<array>.rol(..)`
|
2020-11-16 18:55:31 +03:00
|
|
|
|
|
|
|
|
Roll `<array>` in-place left.
|
2020-12-08 01:53:40 +03:00
|
|
|
```bnf
|
2020-11-16 18:55:31 +03:00
|
|
|
<array>.rol()
|
|
|
|
|
<array>.rol(1)
|
2020-12-08 01:53:40 +03:00
|
|
|
-> <array>
|
2020-11-16 18:55:31 +03:00
|
|
|
|
|
|
|
|
<array>.rol(n)
|
2020-12-08 01:53:40 +03:00
|
|
|
-> <array>
|
2020-11-16 18:55:31 +03:00
|
|
|
```
|
|
|
|
|
|
2021-03-24 02:10:55 +03:00
|
|
|
To roll _right_ pass a negative `n` to `.rol(..)`.
|
2020-11-16 18:55:31 +03:00
|
|
|
|
|
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
### `<array>.compact()`
|
2020-10-07 03:53:10 +03:00
|
|
|
|
2020-12-08 01:53:40 +03:00
|
|
|
```bnf
|
2020-10-07 16:46:59 +03:00
|
|
|
<array>.compact()
|
2020-12-08 01:53:40 +03:00
|
|
|
-> <compact-array>
|
2020-10-07 16:46:59 +03:00
|
|
|
```
|
|
|
|
|
|
2020-10-07 03:53:10 +03:00
|
|
|
Generate a compact `<array>` from a sparse `<array>`, i.e. removing all
|
|
|
|
|
the empty slots.
|
|
|
|
|
|
|
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
### `<array>.len`
|
2020-10-07 03:53:10 +03:00
|
|
|
|
|
|
|
|
Number of non-empty slots/elements in `<array>`.
|
|
|
|
|
|
2020-10-07 16:46:59 +03:00
|
|
|
This is similar to:
|
|
|
|
|
```javascript
|
|
|
|
|
var L = [,,, 1,, 2, 3,,]
|
2020-10-07 03:53:10 +03:00
|
|
|
|
2020-10-07 16:46:59 +03:00
|
|
|
// this is the same as L.len...
|
|
|
|
|
L.compact().length
|
|
|
|
|
```
|
2020-10-07 03:53:10 +03:00
|
|
|
|
2020-10-07 16:46:59 +03:00
|
|
|
Note that this is different from `.length` in that writing to `.len` has
|
|
|
|
|
no effect.
|
2020-10-07 03:53:10 +03:00
|
|
|
|
2021-03-24 02:10:55 +03:00
|
|
|
|
2020-12-08 01:53:40 +03:00
|
|
|
### `<array>.unique()` / `<array>.tailUnique()`
|
2020-10-07 03:53:10 +03:00
|
|
|
|
|
|
|
|
Generate an array with all duplicate elements removed.
|
2020-12-08 01:53:40 +03:00
|
|
|
```bnf
|
|
|
|
|
<array>.unique()
|
|
|
|
|
-> <array>
|
2021-03-24 02:10:55 +03:00
|
|
|
|
|
|
|
|
<array>.tailUnique()
|
|
|
|
|
-> <array>
|
2020-12-08 01:53:40 +03:00
|
|
|
```
|
2020-11-16 18:55:31 +03:00
|
|
|
|
2021-03-24 02:10:55 +03:00
|
|
|
The difference between the two versions is in that `.unique(..)` keeps the
|
|
|
|
|
first occurrence of a value while `.tailUnique(..)` keeps the last.
|
|
|
|
|
|
|
|
|
|
|
2020-12-08 01:53:40 +03:00
|
|
|
### `<array>.trim()` / `<array>.trimStart()` / `<array>.trimEnd()`
|
2020-10-07 03:53:10 +03:00
|
|
|
|
2020-12-08 01:53:40 +03:00
|
|
|
Copy array removing empty slots from array start, end or both.
|
|
|
|
|
```bnf
|
|
|
|
|
<array>.trim()
|
|
|
|
|
-> <array>
|
|
|
|
|
|
|
|
|
|
<array>.trimStart()
|
|
|
|
|
-> <array>
|
|
|
|
|
|
|
|
|
|
<array>.trimEnd()
|
|
|
|
|
-> <array>
|
2020-10-07 16:46:59 +03:00
|
|
|
```
|
2020-12-08 01:53:40 +03:00
|
|
|
|
2021-03-24 02:10:55 +03:00
|
|
|
This is similar to `String`'s equivalent methods but removing _empty_ slots
|
|
|
|
|
instead of spaces.
|
|
|
|
|
|
2020-12-08 01:53:40 +03:00
|
|
|
|
|
|
|
|
### `<array>.cmp(..)`
|
|
|
|
|
|
|
|
|
|
Compare two arrays.
|
|
|
|
|
```bnf
|
2020-10-07 16:46:59 +03:00
|
|
|
<array>.cmp(<other>)
|
2020-12-08 01:53:40 +03:00
|
|
|
-> <bool>
|
2020-10-07 16:46:59 +03:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
This will return `true` if:
|
2021-03-24 02:10:55 +03:00
|
|
|
- `<array> === <other>`
|
|
|
|
|
|
|
|
|
|
or
|
2020-10-07 16:46:59 +03:00
|
|
|
- lengths are the same and,
|
|
|
|
|
- values on the same positions are equal.
|
|
|
|
|
|
2021-03-24 02:10:55 +03:00
|
|
|
<!--
|
|
|
|
|
XXX should this test based on equality or on identity by default???
|
|
|
|
|
...see: Object.match(..)
|
|
|
|
|
-->
|
|
|
|
|
|
2020-10-07 16:46:59 +03:00
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
### `<array>.setCmp(..)`
|
2020-10-07 03:53:10 +03:00
|
|
|
|
2020-12-08 01:53:40 +03:00
|
|
|
Compare to arrays ignoring element order and count.
|
|
|
|
|
```bnf
|
|
|
|
|
<array>.setCmp(<other>)
|
|
|
|
|
-> <bool>
|
|
|
|
|
```
|
|
|
|
|
|
2021-03-24 02:10:55 +03:00
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
### `<array>.sortAs(..)`
|
2020-10-07 03:53:10 +03:00
|
|
|
|
2020-12-08 01:53:40 +03:00
|
|
|
Sort array as a different array.
|
|
|
|
|
```bnf
|
|
|
|
|
<array>.sortAs(<other>)
|
|
|
|
|
-> <array>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Elements not present in `<other>` retain their relative order and are
|
|
|
|
|
placed after the sorted elements.
|
|
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
```javascript
|
|
|
|
|
var L = [1, 2, 3, 4, 5, 6]
|
|
|
|
|
var O = [5, 3, 1, 0]
|
|
|
|
|
|
|
|
|
|
L.sortAs(O) // -> [5, 3, 1, 2, 4, 6]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
### `<array>.inplaceSortAs(..)`
|
2020-10-07 03:53:10 +03:00
|
|
|
|
2020-12-08 01:53:40 +03:00
|
|
|
Sort array as a different array keeping positions of unsorted elements.
|
|
|
|
|
```bnf
|
|
|
|
|
<array>.inplaceSortAs(<other>)
|
|
|
|
|
-> <array>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
```javascript
|
|
|
|
|
var L = [1, 2, 3, 4, 5, 6]
|
|
|
|
|
var O = [5, 3, 1, 0]
|
|
|
|
|
|
|
|
|
|
L.inplaceSortAs(O) // -> [5, 2, 3, 4, 1, 6]
|
|
|
|
|
```
|
|
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
### `<array>.toKeys(..)`
|
2020-10-10 17:27:00 +03:00
|
|
|
|
2020-12-08 01:53:40 +03:00
|
|
|
Create an object with array values as keys and index as value.
|
|
|
|
|
```bnf
|
|
|
|
|
<array>.toKeys()
|
|
|
|
|
-> <object>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Normalize resulting `<object>` keys:
|
|
|
|
|
```bnf
|
|
|
|
|
<array>.toKeys(<normalize>)
|
|
|
|
|
-> <object>
|
|
|
|
|
|
|
|
|
|
<normalize>(<elem>, <index>)
|
|
|
|
|
-> <key>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
If `<array>` contains the same value multiple times it will be written
|
|
|
|
|
to `<object>` only once with the last occurrences' index.
|
|
|
|
|
|
|
|
|
|
Since `object` keys can only be `string`s array items that are not
|
|
|
|
|
strings will be converted to strings. If this is not desired use `.toMap(..)`
|
|
|
|
|
instead.
|
|
|
|
|
|
|
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
### `<array>.toMap(..)`
|
2020-10-10 17:27:00 +03:00
|
|
|
|
2020-12-08 01:53:40 +03:00
|
|
|
Create a map with array values as keys and index as value.
|
|
|
|
|
```bnf
|
|
|
|
|
<array>.toMap()
|
|
|
|
|
-> <map>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Normalize resulting `<map>` keys:
|
|
|
|
|
```bnf
|
|
|
|
|
<array>.toMap(<normalize>)
|
|
|
|
|
-> <map>
|
|
|
|
|
|
|
|
|
|
<normalize>(<elem>, <index>)
|
|
|
|
|
-> <key>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Note that if `<array>` contains the same value multiple times it will be used
|
|
|
|
|
as key only once and retain the last occurrences' index.
|
|
|
|
|
|
|
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
### `Array.zip(..)` / `<array>.zip(..)`
|
2020-10-15 03:12:42 +03:00
|
|
|
|
2020-12-08 01:53:40 +03:00
|
|
|
_Zip_ input array items.
|
|
|
|
|
```bnf
|
|
|
|
|
Array.zip(<array>, <array>, ..)
|
|
|
|
|
-> <array>
|
|
|
|
|
|
|
|
|
|
<array>.zip(<array>, <array>, ..)
|
|
|
|
|
-> <array>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
```javascript
|
|
|
|
|
var A = [1, 2, 3]
|
|
|
|
|
var B = ['a', 'b', 'c', 'd']
|
|
|
|
|
|
|
|
|
|
Array.zip(A, B) // -> [[1, 'a'], [2, 'b'], [3, 'c'], [, 'd']]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Array _sparseness_ is retained -- if one of the arrays has an empty slot, or is
|
|
|
|
|
not long enough, the corresponding spot in the result will be empty.
|
|
|
|
|
|
|
|
|
|
Resulting array length is strictly equal to the longest input array length.
|
|
|
|
|
|
|
|
|
|
|
2020-11-18 06:59:56 +03:00
|
|
|
### `Array.iter(..)` / `<array>.iter()`
|
2020-11-10 03:04:04 +03:00
|
|
|
|
|
|
|
|
Return an iterator/generator from the current array.
|
|
|
|
|
|
2020-11-10 03:25:00 +03:00
|
|
|
This is mostly useful in combination with the [Generator extensions and utilities](#generator-extensions-and-utilities)
|
2020-11-10 03:04:04 +03:00
|
|
|
|
2020-10-10 17:27:00 +03:00
|
|
|
|
2020-11-07 03:19:52 +03:00
|
|
|
### Abortable `Array` iteration
|
|
|
|
|
|
2020-11-16 18:55:31 +03:00
|
|
|
A an alternative to `Array`'s `.map(..)` / `.filter(..)` / .. methods with ability to
|
2020-11-23 22:27:30 +03:00
|
|
|
stop the iteration process by `throw`ing `STOP` or `STOP(<value>)`.
|
2020-11-07 03:19:52 +03:00
|
|
|
|
|
|
|
|
```javascript
|
2020-11-23 22:27:30 +03:00
|
|
|
var {STOP} = require('ig-types/Array')
|
2020-11-07 03:19:52 +03:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
This can be used in two ways:
|
|
|
|
|
|
|
|
|
|
1) `throw` as-is to simply stop...
|
|
|
|
|
```javascript
|
|
|
|
|
;[1,2,3,4,5]
|
|
|
|
|
.smap(function(e){
|
|
|
|
|
// simply abort here and now...
|
2020-11-23 22:27:30 +03:00
|
|
|
throw STOP })
|
2020-11-07 03:19:52 +03:00
|
|
|
```
|
2020-11-23 22:27:30 +03:00
|
|
|
Since we aborted the iteration without passing any arguments to `STOP`,
|
2020-11-07 03:19:52 +03:00
|
|
|
`.smap(..)` will return `undefined`.
|
|
|
|
|
|
|
|
|
|
2) `throw` an instance and return the argument...
|
|
|
|
|
```javascript
|
2020-11-23 22:27:30 +03:00
|
|
|
// this will print "4" -- the value passed to STOP...
|
2020-11-07 03:19:52 +03:00
|
|
|
console.log([1,2,3,4,5]
|
|
|
|
|
.smap(function(e){
|
|
|
|
|
if(e > 3){
|
|
|
|
|
// NOTE: new is optional here...
|
|
|
|
|
// ...StopIteratiom is an object.js constructor.
|
2020-11-23 22:27:30 +03:00
|
|
|
throw new STOP(e) } }))
|
2020-11-07 03:19:52 +03:00
|
|
|
```
|
|
|
|
|
|
2020-11-23 22:27:30 +03:00
|
|
|
Note that no partial result is returned unless passed through `STOP(..)`.
|
2020-11-16 18:55:31 +03:00
|
|
|
|
|
|
|
|
|
2020-11-23 22:27:30 +03:00
|
|
|
#### `array.STOP` / `array.STOP(..)`
|
2020-11-16 18:55:31 +03:00
|
|
|
|
2020-11-23 22:27:30 +03:00
|
|
|
An _object/constructor_ that if raised (as an exception) while iterating via
|
|
|
|
|
a supporting iterator method will abort further execution and correctly exit.
|
2020-11-07 03:19:52 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
#### `<array>.smap(..)` / `<array>.sfilter(..)` / `<array>.sreduce(..)` / `<array>.sforEach(..)`
|
|
|
|
|
|
|
|
|
|
Like `Array`'s `.map(..)`, `.filter(..)`, `.reduce(..)` and `.forEach(..)` but
|
2020-11-23 22:27:30 +03:00
|
|
|
with added support for aborting iteration by throwing `STOP` or `STOP(<value>)`.
|
2020-11-07 03:19:52 +03:00
|
|
|
|
|
|
|
|
|
2020-10-10 17:27:00 +03:00
|
|
|
### Large `Array` iteration (chunked)
|
|
|
|
|
|
|
|
|
|
Iterating over very large `Array` instances in JavaScript can block execution,
|
|
|
|
|
to avoid this `types.js` implements `.map(..)`/`.filter(..)`/`.reduce(..)`
|
2020-10-11 03:09:48 +03:00
|
|
|
equivalent methods that iterate the array in chunks and do it asynchronously
|
|
|
|
|
giving the runtime a chance to run in between.
|
|
|
|
|
|
|
|
|
|
In the simplest cases these are almost a drop-in replacements for the equivalent
|
|
|
|
|
methods but return a promise.
|
|
|
|
|
```javascript
|
|
|
|
|
var a = [1,2,3,4,5]
|
|
|
|
|
.map(function(e){
|
|
|
|
|
return e*2 })
|
|
|
|
|
|
|
|
|
|
var b
|
|
|
|
|
;[1,2,3,4,5]
|
|
|
|
|
.mapChunks(function(e){
|
|
|
|
|
return e*2 })
|
|
|
|
|
.then(function(res){
|
|
|
|
|
b = res })
|
|
|
|
|
|
|
|
|
|
// or with await...
|
|
|
|
|
var c = await [1,2,3,4,5]
|
|
|
|
|
.mapChunks(function(e){
|
|
|
|
|
return e*2 })
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
These support setting the chunk size (default: `50`) as the first argument:
|
|
|
|
|
```javascript
|
2020-11-07 03:19:52 +03:00
|
|
|
var c = await [1,2,3,4,5]
|
|
|
|
|
.mapChunks(2, function(e){
|
|
|
|
|
return e*2 })
|
2020-10-11 03:09:48 +03:00
|
|
|
```
|
|
|
|
|
|
2020-11-23 22:27:30 +03:00
|
|
|
#### `array.STOP` / `array.STOP(..)`
|
2020-11-06 16:57:51 +03:00
|
|
|
|
2020-11-07 03:19:52 +03:00
|
|
|
Like for [`<array>.smap(..)` and friends](#abortable-array-iteration) iteration
|
2020-11-23 22:27:30 +03:00
|
|
|
can be stopped by throwing a `array.STOP` / `array.STOP(<value>)` and as before
|
|
|
|
|
there are two ways to go:
|
2020-11-06 16:57:51 +03:00
|
|
|
|
|
|
|
|
1) `throw` as-is to simply stop
|
|
|
|
|
```javascript
|
|
|
|
|
;[1,2,3,4,5]
|
|
|
|
|
.mapChunks(function(e){
|
|
|
|
|
// simply abort here and now...
|
2020-11-23 22:27:30 +03:00
|
|
|
throw STOP })
|
2020-11-06 16:57:51 +03:00
|
|
|
.catch(function(){
|
|
|
|
|
console.log('done.') })
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
2) `Throw` an instance and pass a value to `.catch(..)`
|
|
|
|
|
```javascript
|
|
|
|
|
;[1,2,3,4,5]
|
|
|
|
|
.mapChunks(function(e){
|
|
|
|
|
if(e > 3){
|
|
|
|
|
// NOTE: new is optional here...
|
|
|
|
|
// ...StopIteratiom is an object.js constructor.
|
2020-11-23 22:27:30 +03:00
|
|
|
throw new STOP(e) } })
|
2020-11-06 16:57:51 +03:00
|
|
|
.catch(function(e){
|
2020-11-07 03:19:52 +03:00
|
|
|
console.log('first value greater than 3:', e) })
|
2020-11-06 16:57:51 +03:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
2020-10-11 03:09:48 +03:00
|
|
|
#### `<array>.CHUNK_SIZE`
|
|
|
|
|
|
2020-11-06 16:57:51 +03:00
|
|
|
The default iteration chunk size.
|
|
|
|
|
|
|
|
|
|
Note that the smaller this is the more _responsive_ the code is, especially
|
|
|
|
|
in UI applications but there is a small overhead added per chunk.
|
|
|
|
|
|
|
|
|
|
Default value: `50`
|
|
|
|
|
|
2020-10-10 17:27:00 +03:00
|
|
|
|
2020-12-08 01:53:40 +03:00
|
|
|
#### `<array>.mapChunks(..)` / `<array>.filterChunks(..)` / `<array>.reduceChunks(..)`
|
2020-10-07 03:53:10 +03:00
|
|
|
|
2020-12-08 01:53:40 +03:00
|
|
|
The `.map(..)`, `.filter(..)` and `.reduce(..)` alternatives respectively:
|
|
|
|
|
```bnf
|
2020-10-11 03:09:48 +03:00
|
|
|
<array>.mapChunks(<func>)
|
|
|
|
|
<array>.mapChunks(<chunk-size>, <func>)
|
|
|
|
|
-> <promise>
|
|
|
|
|
|
|
|
|
|
<func>(<item>, <index>, <array>)
|
|
|
|
|
-> <new-item>
|
|
|
|
|
```
|
|
|
|
|
|
2020-12-08 01:53:40 +03:00
|
|
|
```bnf
|
|
|
|
|
<array>.filterChunks(<func>)
|
|
|
|
|
<array>.filterChunks(<chunk-size>, <func>)
|
|
|
|
|
-> <promise>
|
|
|
|
|
|
|
|
|
|
<func>(<item>, <index>, <array>)
|
|
|
|
|
-> <bool>
|
2020-10-11 03:09:48 +03:00
|
|
|
```
|
2020-12-08 01:53:40 +03:00
|
|
|
|
|
|
|
|
```bnf
|
|
|
|
|
<array>.reduceChunks(<func>, <state>)
|
|
|
|
|
<array>.mreduceChunks(<chunk-size>, <func>, <state>)
|
|
|
|
|
-> <promise>
|
|
|
|
|
|
|
|
|
|
<func>(<state>, <item>, <index>, <array>)
|
|
|
|
|
-> <state>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
All three support chunk handlers in the same way (illustrated on `.mapChunks(..)`):
|
|
|
|
|
```bnf
|
2020-10-11 03:09:48 +03:00
|
|
|
<array>.mapChunks([<func>, <chunk-handler>])
|
|
|
|
|
<array>.mapChunks(<chunk-size>, [<func>, <chunk-handler>])
|
|
|
|
|
-> <promise>
|
|
|
|
|
|
|
|
|
|
<func>(<item>, <index>, <array>)
|
|
|
|
|
-> <new-item>
|
|
|
|
|
|
|
|
|
|
<chunk-handler>(<chunk>, <result>, <offset>)
|
|
|
|
|
```
|
|
|
|
|
|
2020-12-08 01:53:40 +03:00
|
|
|
The `<chunk-handler>` gets the completed chunk of data after it is computed
|
|
|
|
|
but before the timeout.
|
2020-10-11 03:09:48 +03:00
|
|
|
|
2020-10-07 03:53:10 +03:00
|
|
|
|
|
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
## `Map`
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
require('ig-types/Map')
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### `<map>.sort(..)`
|
|
|
|
|
|
|
|
|
|
|
2020-12-08 01:53:40 +03:00
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
## `Set`
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
require('ig-types/Set')
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### `<set>.unite(..)`
|
|
|
|
|
|
|
|
|
|
### `<set>.intersect(..)`
|
2020-10-07 16:46:59 +03:00
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
### `<set>.subtract(..)`
|
2020-10-07 16:46:59 +03:00
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
### `<set>.sort(..)`
|
2020-10-07 16:46:59 +03:00
|
|
|
|
2020-10-07 03:53:10 +03:00
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
## `Date`
|
2020-10-07 03:53:10 +03:00
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
```javascript
|
|
|
|
|
require('ig-types/Date')
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### `Date.timeStamp(..)`
|
2020-10-07 03:53:10 +03:00
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
### `Date.fromTimeStamp(..)`
|
2020-10-07 03:53:10 +03:00
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
### `Date.str2ms(..)`
|
2020-10-07 16:46:59 +03:00
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
### `<date>.toShortDate(..)`
|
2020-10-07 03:53:10 +03:00
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
### `<date>.getTimeStamp(..)`
|
2020-10-07 03:53:10 +03:00
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
### `<date>.setTimeStamp(..)`
|
2020-10-07 03:53:10 +03:00
|
|
|
|
|
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
## `String`
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
require('ig-types/String')
|
|
|
|
|
```
|
2020-10-07 03:53:10 +03:00
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
### `<string>.capitalize()`
|
2020-10-07 03:53:10 +03:00
|
|
|
|
2020-12-17 18:55:28 +03:00
|
|
|
### `<string>.indent(..)`
|
|
|
|
|
|
2020-10-07 03:53:10 +03:00
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
## `RegExp`
|
2020-10-07 03:53:10 +03:00
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
```javascript
|
|
|
|
|
require('ig-types/RegExp')
|
|
|
|
|
```
|
2020-10-07 03:53:10 +03:00
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
### `RegExp.quoteRegExp(..)`
|
2020-10-07 03:53:10 +03:00
|
|
|
|
|
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
## `Promise`
|
2020-10-07 03:53:10 +03:00
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
```javascript
|
|
|
|
|
require('ig-types/Promise')
|
|
|
|
|
```
|
|
|
|
|
or
|
|
|
|
|
```javascript
|
|
|
|
|
var promise = require('ig-types/Promise')
|
|
|
|
|
```
|
2020-10-07 03:53:10 +03:00
|
|
|
|
|
|
|
|
|
2020-11-10 03:04:04 +03:00
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
### Cooperative promises
|
2020-11-03 05:22:29 +03:00
|
|
|
|
|
|
|
|
#### `Promise.cooperative(..)`
|
|
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
#### `<promise-coop>.set(..)`
|
|
|
|
|
|
|
|
|
|
#### `<promise-coop>.isSet`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### Promise iteration
|
|
|
|
|
|
|
|
|
|
An _iterable promise_ is on one hand very similar to `Promise.all(..)` in that it
|
|
|
|
|
generally takes a list of values each could be either an explicit value or a
|
|
|
|
|
promise, and it is similar to a _generator_ in that allows iteration over the
|
|
|
|
|
contained values and chaining of operations but unlike `Promise.all(..)` this
|
|
|
|
|
iteration occurs depth first instead of breadth first.
|
|
|
|
|
|
2020-11-18 06:59:56 +03:00
|
|
|
Essentially one can think about _promise iterators_ vs. _generators_ as the former
|
|
|
|
|
being internally controlled and asynchronous while the later being externally
|
|
|
|
|
controlled and synchronous.
|
|
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
Here is a traditional example using `Promise.all(..)`:
|
|
|
|
|
```javascript
|
|
|
|
|
var p = Promise.all([ .. ])
|
|
|
|
|
// this will not execute until ALL the inputs resolve...
|
|
|
|
|
.then(function(lst){
|
|
|
|
|
return lst
|
|
|
|
|
.filter(function(e){
|
|
|
|
|
|
|
|
|
|
})
|
|
|
|
|
// this will not run until ALL of lst is filtered...
|
|
|
|
|
.map(function(e){
|
|
|
|
|
|
|
|
|
|
}) })
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
var p = Promise.iter([ .. ])
|
|
|
|
|
// each element is processed as soon as it is ready disregarding of its order
|
|
|
|
|
// in the input array...
|
|
|
|
|
.filter(function(e){
|
|
|
|
|
|
|
|
|
|
})
|
|
|
|
|
// items reach here as soon as they are returned by the filter stage...
|
|
|
|
|
// NOTE: the filter handler may return promises, those will not be processed
|
|
|
|
|
// until they are resolved...
|
|
|
|
|
.map(function(e){
|
|
|
|
|
|
|
|
|
|
})
|
|
|
|
|
// .then(..) explicitly waits for the whole list of inputs to resolve...
|
|
|
|
|
.then(function(lst){
|
|
|
|
|
|
|
|
|
|
})
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
This approach has a number of advantages:
|
|
|
|
|
- items are processed as soon as they are available without waiting for the
|
|
|
|
|
slowest promise on each level to resolve
|
|
|
|
|
- simpler and more intuitive code
|
|
|
|
|
|
|
|
|
|
And some disadvantages:
|
|
|
|
|
- item indexes are unknowable until all the promises resolve.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#### `Promise.iter(..)` / `promise.IterablePromise(..)`
|
|
|
|
|
|
|
|
|
|
Create an _iterable promise_
|
|
|
|
|
```
|
|
|
|
|
Promise.iter(<array>)
|
|
|
|
|
-> <iterable-promise>
|
|
|
|
|
```
|
|
|
|
|
#### `<promise-iter>.map(..)` / `<promise-iter>.filter(..)` / `<promise-iter>.reduce(..)`
|
|
|
|
|
|
|
|
|
|
#### `<promise-iter>.flat(..)`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#### `<promise-iter>.then(..)` / `<promise-iter>.catch(..)` / `<promise-iter>.finally(..)`
|
|
|
|
|
|
|
|
|
|
#### Advanced handler
|
|
|
|
|
|
2020-12-08 01:53:40 +03:00
|
|
|
```bnf
|
2020-11-18 06:09:43 +03:00
|
|
|
Promise.iter(<block-array>, <handler>)
|
|
|
|
|
-> <iterable-promise>
|
|
|
|
|
|
|
|
|
|
<handler>(<elem>)
|
|
|
|
|
-> [ <elems> ]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```bnf
|
|
|
|
|
<block-array> ::=
|
|
|
|
|
[]
|
|
|
|
|
| [ <block-elem>, .. ]
|
|
|
|
|
|
|
|
|
|
<block-elem> ::=
|
|
|
|
|
[]
|
|
|
|
|
| [ <value>, .. ]
|
|
|
|
|
| <promise>
|
|
|
|
|
| <non-array>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
```javascript
|
|
|
|
|
var p = Promise.iter(
|
|
|
|
|
// NOTE: if you want an element to explicitly be an array wrap it in
|
|
|
|
|
// an array -- like the last element here...
|
|
|
|
|
[[1, 2], 3, Promise.resolve(4), [[5, 6]]],
|
|
|
|
|
function(elem){
|
|
|
|
|
return elem % 2 == 0 ?
|
|
|
|
|
[elem, elem]
|
|
|
|
|
: elem instanceof Array ?
|
|
|
|
|
[elem]
|
|
|
|
|
: [] })
|
|
|
|
|
.then(function(lst){
|
|
|
|
|
console.log(lst) // -> [2, 2, 4, 4, [5, 6]]
|
|
|
|
|
})
|
|
|
|
|
```
|
2020-11-03 05:22:29 +03:00
|
|
|
|
2020-10-07 03:53:10 +03:00
|
|
|
|
2020-11-10 03:25:00 +03:00
|
|
|
## Generator extensions and utilities
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
var generator = require('ig-types/generator')
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### The basics
|
|
|
|
|
|
2021-03-24 18:57:02 +03:00
|
|
|
The _generator_ hierarchy in JavaScript is a bit complicated.
|
|
|
|
|
|
|
|
|
|
Consider the following:
|
|
|
|
|
```javascript
|
|
|
|
|
// generator constructor function...
|
|
|
|
|
var Iter = function*(L){
|
|
|
|
|
for(var e of L){
|
|
|
|
|
yield e }}
|
|
|
|
|
|
|
|
|
|
// generator instance...
|
|
|
|
|
var iter = Iter([1, 2, 3])
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
We can test that `iter` is an instance of `Iter`:
|
|
|
|
|
```javascript
|
|
|
|
|
iter instanceof Iter // -> true
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#### `generator.Generator`
|
|
|
|
|
|
|
|
|
|
Exposes the _hidden_ JavaScript generator constructor.
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
Iter instanceof generator.Generator // -> true
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Note that currently in JavaScript there is no built-in way to test if a
|
|
|
|
|
constructor, `Iter` in this case, is a _generator_ constructor.
|
|
|
|
|
|
2020-11-10 03:25:00 +03:00
|
|
|
|
|
|
|
|
#### `generator.iter(..)`
|
2020-11-10 03:04:04 +03:00
|
|
|
|
2021-03-24 18:57:02 +03:00
|
|
|
Generic generator wrapper
|
|
|
|
|
```bnf
|
|
|
|
|
generator.iter()
|
|
|
|
|
-> <generator>
|
|
|
|
|
|
|
|
|
|
generator.iter(<iterable>)
|
|
|
|
|
-> <generator>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
```javascript
|
|
|
|
|
for(var i of generator.iter([1, 2, 3])){
|
|
|
|
|
console.log(i) }
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The following are equivalent:
|
|
|
|
|
```javascript
|
|
|
|
|
var b = generator.iter()
|
|
|
|
|
|
|
|
|
|
var a = new generator.Generator()
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
But `Generator()` takes no arguments and thus can not be used as a wrapper.
|
|
|
|
|
|
2020-11-10 03:04:04 +03:00
|
|
|
|
|
|
|
|
### Generator instance iteration
|
|
|
|
|
|
2021-03-25 02:59:15 +03:00
|
|
|
This is a set of `Array`-like iterator methods that enable chaining of
|
2021-03-25 14:40:51 +03:00
|
|
|
generators and `Promise`-like API to handle the generated results.
|
2021-03-25 02:59:15 +03:00
|
|
|
|
|
|
|
|
Chained generators handle items depth-first, i.e. the items are passed as they are yielded down the generator chain.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#### `<generator>.map(..)` / `<generator>.filter(..)` / `<generator>.reduce(..)`
|
|
|
|
|
|
|
|
|
|
Equivalents to `Array`'s `.map(..)`, `.filter(..)` and `.reduce(..)` but return
|
|
|
|
|
generators that yield the handler return values.
|
|
|
|
|
|
2021-03-25 14:40:51 +03:00
|
|
|
<!--
|
|
|
|
|
XXX .reduce(..) can return a non-iterable -- test and document this case...
|
|
|
|
|
-->
|
|
|
|
|
|
2021-03-25 02:59:15 +03:00
|
|
|
|
|
|
|
|
#### `<generator>.slice(..)`
|
|
|
|
|
|
2021-03-25 14:40:51 +03:00
|
|
|
```bnf
|
|
|
|
|
<generator>.slice()
|
|
|
|
|
<generator>.slice(<from>)
|
|
|
|
|
<generator>.slice(<from>, <to>)
|
|
|
|
|
-> <generator>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
2021-03-25 02:59:15 +03:00
|
|
|
#### `<generator>.at(..)`
|
|
|
|
|
|
2021-03-25 14:40:51 +03:00
|
|
|
```bnf
|
|
|
|
|
<generator>.at(<index>)
|
|
|
|
|
-> <generator>
|
|
|
|
|
```
|
|
|
|
|
Returns a generator that will yield an item at a specific position when it is
|
|
|
|
|
available.
|
|
|
|
|
|
|
|
|
|
|
2021-03-25 02:59:15 +03:00
|
|
|
#### `<generator>.flat(..)`
|
|
|
|
|
|
2021-03-25 14:40:51 +03:00
|
|
|
```bnf
|
|
|
|
|
<generator>.flat()
|
|
|
|
|
<generator>.flat(<depth>)
|
|
|
|
|
-> <generator>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
2021-03-25 02:59:15 +03:00
|
|
|
#### `<generator>.shift()` / `<generator>.pop()`
|
|
|
|
|
|
|
|
|
|
Return a generator yielding the first/last sequence item.
|
|
|
|
|
|
|
|
|
|
Note that there are no equivalents to `.push(..)` or `.unshift(..)` as they
|
|
|
|
|
need break item processing order.
|
|
|
|
|
|
2020-11-10 03:04:04 +03:00
|
|
|
|
|
|
|
|
#### `<generator>.promise()`
|
|
|
|
|
|
2021-03-25 14:40:51 +03:00
|
|
|
```bnf
|
|
|
|
|
<generator>.promise()
|
|
|
|
|
-> <promise>
|
|
|
|
|
```
|
|
|
|
|
Return a promise and resolve it with the generator value.
|
|
|
|
|
|
|
|
|
|
Note that this will deplete the generator.
|
|
|
|
|
|
|
|
|
|
|
2020-11-10 03:04:04 +03:00
|
|
|
#### `<generator>.then(..)` / `<generator>.catch(..)` / `<generator>.finally(..)`
|
|
|
|
|
|
2021-03-25 14:40:51 +03:00
|
|
|
```bnf
|
|
|
|
|
<generator>.then(<resolve>, <reject>)
|
|
|
|
|
-> <promise>
|
|
|
|
|
|
|
|
|
|
<generator>.then(<reject>)
|
|
|
|
|
-> <promise>
|
|
|
|
|
|
|
|
|
|
<generator>.finally(<handler>)
|
|
|
|
|
-> <promise>
|
|
|
|
|
```
|
|
|
|
|
Shorthands to `<generator>.promise().then(..)` / `<generator>.promise().catch(..)` / `<generator>.promise().finally(..)`
|
|
|
|
|
|
|
|
|
|
|
2020-11-10 03:04:04 +03:00
|
|
|
#### `<generator>.toArray()`
|
|
|
|
|
|
2021-03-25 14:40:51 +03:00
|
|
|
```bnf
|
|
|
|
|
<generator>.toArray()
|
|
|
|
|
-> <array>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
This is equivalent to `[...<generator>]`.
|
|
|
|
|
|
2020-11-10 03:04:04 +03:00
|
|
|
|
2020-11-18 06:59:56 +03:00
|
|
|
### Generator constructor iteration
|
2020-11-10 03:04:04 +03:00
|
|
|
|
|
|
|
|
```javascript
|
2020-11-10 03:25:00 +03:00
|
|
|
var sumOdds = generator.iter
|
2020-11-10 03:04:04 +03:00
|
|
|
.filter(function(e){
|
|
|
|
|
return e % 2 == 1 })
|
|
|
|
|
.reduce(function(r, e){
|
|
|
|
|
return r + e }, 0)
|
|
|
|
|
.pop()
|
|
|
|
|
|
2020-11-10 03:25:00 +03:00
|
|
|
console.log(sumOdds([1, 2, 3])) // -> 4
|
2020-11-10 03:04:04 +03:00
|
|
|
console.log(sumOdds([1, 2, 3, 4, 5, 6, 7])) // -> 16
|
2020-11-10 03:25:00 +03:00
|
|
|
```
|
2020-11-10 03:04:04 +03:00
|
|
|
|
2020-11-10 03:25:00 +03:00
|
|
|
The above code is the same in function to:
|
|
|
|
|
```javascript
|
|
|
|
|
var sumOdds = function(lst){
|
|
|
|
|
return generator.iter(lst)
|
|
|
|
|
.filter(function(e){
|
|
|
|
|
return e % 2 == 1 })
|
|
|
|
|
.reduce(function(r, e){
|
|
|
|
|
return r + e }, 0)
|
|
|
|
|
.pop() }
|
|
|
|
|
|
|
|
|
|
console.log(sumOdds([1, 2, 3])) // -> 4
|
|
|
|
|
console.log(sumOdds([1, 2, 3, 4, 5, 6, 7])) // -> 16
|
2020-11-10 03:04:04 +03:00
|
|
|
```
|
|
|
|
|
|
2021-03-24 18:57:02 +03:00
|
|
|
#### `<Generator>.at(..)`
|
2020-11-10 03:25:00 +03:00
|
|
|
|
2021-03-24 18:57:02 +03:00
|
|
|
#### `<Generator>.shift()` / `<Generator>.pop()`
|
2020-11-10 03:04:04 +03:00
|
|
|
|
2021-03-24 18:57:02 +03:00
|
|
|
#### `<Generator>.slice(..)`
|
2020-11-10 03:04:04 +03:00
|
|
|
|
|
|
|
|
This is like `Array`'s `.slice(..)` but does not support negative indexes.
|
|
|
|
|
|
2021-03-24 18:57:02 +03:00
|
|
|
#### `<Generator>.map(..)` / `<Generator>.filter(..)` / `<Generator>.reduce(..)` / `<Generator>.flat()`
|
2020-11-10 03:04:04 +03:00
|
|
|
|
2021-03-24 18:57:02 +03:00
|
|
|
#### `<Generator>.toArray()`
|
2020-11-10 03:04:04 +03:00
|
|
|
|
2021-03-24 18:57:02 +03:00
|
|
|
#### `<Generator>.then(..)` / `<Generator>.catch(..)` / `<Generator>.finally(..)`
|
2020-11-10 03:04:04 +03:00
|
|
|
|
|
|
|
|
|
2020-10-07 03:53:10 +03:00
|
|
|
## Containers
|
|
|
|
|
|
2020-10-07 07:33:58 +03:00
|
|
|
```javascript
|
|
|
|
|
var containers = require('ig-types').containers
|
|
|
|
|
```
|
|
|
|
|
or, to only import containers:
|
|
|
|
|
```javascript
|
|
|
|
|
var containers = require('ig-types/containers')
|
|
|
|
|
```
|
2020-10-07 03:53:10 +03:00
|
|
|
|
2020-10-10 06:31:29 +03:00
|
|
|
Note that this will also import `ig-types/Map`.
|
2020-10-07 16:46:59 +03:00
|
|
|
|
|
|
|
|
|
2020-10-07 07:33:58 +03:00
|
|
|
### `containers.UniqueKeyMap()` (`Map`)
|
|
|
|
|
|
|
|
|
|
`UniqueKeyMap` implements a key-value container (i.e. `Map`) that supports
|
|
|
|
|
and maintains _duplicate_ keys by appending an index to them.
|
|
|
|
|
The original keys are stored internally thus the renaming mechanics are
|
|
|
|
|
stable.
|
|
|
|
|
|
|
|
|
|
`UniqueKeyMap` extends the `Map` constructor, so all the usual `Map`
|
|
|
|
|
methods and properties apply here.
|
|
|
|
|
|
|
|
|
|
To construct an instance:
|
|
|
|
|
```javascript
|
|
|
|
|
var x = new UniqueKeyMap()
|
|
|
|
|
```
|
|
|
|
|
or:
|
|
|
|
|
```javascript
|
|
|
|
|
// new is optional...
|
|
|
|
|
var y = UniqueKeyMap()
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
`UniqueKeyMap` supports the same initialization signature as `Map` but
|
|
|
|
|
treats repeating keys differently.
|
|
|
|
|
```javascript
|
|
|
|
|
var z = UniqueKeyMap([['a', 1], ['a', 2], ['b', 1]])
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The second `"a"` item will automatically get re-keyed as `"a (1)"`:
|
|
|
|
|
```javascript
|
|
|
|
|
console.log([...z.keys()]) // -> ['a', 'a (1)', 'b']
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Note that `.set(..)` will never rewrite an element:
|
|
|
|
|
```javascript
|
|
|
|
|
z.set('a', 3)
|
|
|
|
|
|
|
|
|
|
console.log([...z.keys()]) // -> ['a', 'a (1)', 'b', 'a (2)']
|
|
|
|
|
|
|
|
|
|
z.get('a') // -> 1
|
|
|
|
|
z.get('a (1)') // -> 2
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
To get the generated key:
|
|
|
|
|
```javascript
|
|
|
|
|
var k = z.set('a', 4, true)
|
|
|
|
|
|
|
|
|
|
console.log(k) // -> 'a (3)'
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
To explicitly rewrite an item:
|
|
|
|
|
```javascript
|
|
|
|
|
z.reset('a (1)', 4)
|
|
|
|
|
|
|
|
|
|
z.get('a (1)') // -> 4
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
And we can _rename_ items, i.e. change their key:
|
|
|
|
|
```javascript
|
|
|
|
|
z.rename('a (2)', 'c')
|
|
|
|
|
|
|
|
|
|
console.log([...z.keys()]) // -> ['a', 'a (1)', 'b', 'a (3)', 'c']
|
|
|
|
|
```
|
2020-10-07 03:53:10 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
For more info on `Map` see:
|
|
|
|
|
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
|
|
|
|
|
|
2020-10-07 07:33:58 +03:00
|
|
|
|
2020-10-07 14:48:47 +03:00
|
|
|
#### `<unique-key-map>.set(..)`
|
|
|
|
|
|
2020-12-08 01:53:40 +03:00
|
|
|
```bnf
|
2020-10-07 14:48:47 +03:00
|
|
|
<unique-key-map>.reset(<key>, <item>)
|
|
|
|
|
-> <unique-key-map>
|
|
|
|
|
|
|
|
|
|
<unique-key-map>.reset(<key>, <item>, true)
|
|
|
|
|
-> <new-key>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Add an `<item>` to `<unique-key-map>`.
|
|
|
|
|
|
|
|
|
|
If `<key>` already exists then add an index to it to make it unique.
|
|
|
|
|
|
|
|
|
|
Key updating is done via [`<unique-key-map>.__key_pattern__`](#unique-key-map__key_pattern__).
|
|
|
|
|
|
|
|
|
|
|
2020-10-07 03:53:10 +03:00
|
|
|
#### `<unique-key-map>.reset(..)`
|
|
|
|
|
|
2020-12-08 01:53:40 +03:00
|
|
|
```bnf
|
2020-10-07 14:48:47 +03:00
|
|
|
<unique-key-map>.reset(<key>, <item>)
|
|
|
|
|
-> <unique-key-map>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Explicitly write an `<item>` under `<key>` as-is, this is like `Map`'s `.set(..)`.
|
2020-10-07 03:53:10 +03:00
|
|
|
|
|
|
|
|
#### `<unique-key-map>.rename(..)`
|
|
|
|
|
|
2020-12-08 01:53:40 +03:00
|
|
|
```bnf
|
2020-10-07 15:09:36 +03:00
|
|
|
<unique-key-map>.rename(<from-key>, <to-key>)
|
|
|
|
|
-> <unique-key-map>
|
|
|
|
|
|
|
|
|
|
<unique-key-map>.rename(<from-key>, <to-key>, true)
|
|
|
|
|
-> <new-key>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Rename item key from `<from-key>` to `<to-key>`.
|
|
|
|
|
|
|
|
|
|
Same mechanics apply as for [`.set(..)`](#unique-key-mapset) for key uniqueness.
|
|
|
|
|
|
|
|
|
|
Note, if [`.__unordered_rename__`](#unique-key-map__unordered_rename__) is
|
|
|
|
|
`false` (default) this calls [`.orderedRename(..)`](#unique-key-maporderedrename)
|
|
|
|
|
otherwise [`.unorderedRename(..)`](#unique-key-mapunorderedrename) is called.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#### `<unique-key-map>.orderedRename(..)`
|
|
|
|
|
|
2020-10-07 14:48:47 +03:00
|
|
|
#### `<unique-key-map>.unorderedRename(..)`
|
|
|
|
|
|
2020-10-07 03:53:10 +03:00
|
|
|
#### `<unique-key-map>.keysOf(..)`
|
|
|
|
|
|
2020-10-07 14:48:47 +03:00
|
|
|
#### `<unique-key-map>.originalKey(..)`
|
|
|
|
|
|
|
|
|
|
#### `<unique-key-map>.uniqueKey(..)`
|
|
|
|
|
|
2020-10-07 07:33:58 +03:00
|
|
|
#### `<unique-key-map>.__key_pattern__`
|
|
|
|
|
|
2020-10-07 15:09:36 +03:00
|
|
|
#### `<unique-key-map>.__unordered_rename__`
|
|
|
|
|
|
2020-10-07 07:33:58 +03:00
|
|
|
|
2020-11-15 05:13:35 +03:00
|
|
|
## Event
|
|
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
```javascript
|
|
|
|
|
var event = require('ig-types/event')
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
2020-11-15 05:13:35 +03:00
|
|
|
### `event.Eventfull(..)`
|
|
|
|
|
|
|
|
|
|
### `event.Event(..)`
|
|
|
|
|
|
2020-11-16 02:38:19 +03:00
|
|
|
### `event.TRIGGER`
|
|
|
|
|
|
|
|
|
|
Special value when passed to an event method as first argument will force it
|
|
|
|
|
to trigger event if the first argument was a function.
|
|
|
|
|
|
2020-11-15 05:13:35 +03:00
|
|
|
### `event.EventHandlerMixin`
|
|
|
|
|
|
|
|
|
|
#### `<obj>.on(..)`
|
|
|
|
|
|
|
|
|
|
#### `<obj>.one(..)`
|
|
|
|
|
|
|
|
|
|
#### `<obj>.off(..)`
|
|
|
|
|
|
|
|
|
|
#### `<obj>.trigger(..)`
|
|
|
|
|
|
|
|
|
|
### `event.EventDocMixin`
|
|
|
|
|
|
|
|
|
|
#### `<obj>.eventfull`
|
|
|
|
|
|
|
|
|
|
#### `<obj>.events`
|
|
|
|
|
|
|
|
|
|
### `event.EventMixin`
|
|
|
|
|
|
2020-11-28 03:47:31 +03:00
|
|
|
Combines [`event.EventHandlerMixin`](#eventeventhandlermixin) and
|
|
|
|
|
[`event.EventDocMixin`](#eventeventdocmixin).
|
|
|
|
|
|
2020-11-07 03:19:52 +03:00
|
|
|
## Runner
|
|
|
|
|
|
2020-11-18 06:09:43 +03:00
|
|
|
```javascript
|
|
|
|
|
var runner = require('ig-types/runner')
|
|
|
|
|
```
|
|
|
|
|
|
2020-11-28 03:47:31 +03:00
|
|
|
### Micro task queue
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
This includes [`event.EventMixin`](#eventeventmixin).
|
2020-11-18 06:09:43 +03:00
|
|
|
|
2020-12-17 18:55:28 +03:00
|
|
|
#### `STOP`
|
|
|
|
|
|
|
|
|
|
#### `SKIP`
|
|
|
|
|
|
|
|
|
|
|
2020-12-08 01:53:40 +03:00
|
|
|
#### `Queue(..)` / `Queue.runTasks(..)`
|
|
|
|
|
|
|
|
|
|
#### `Queue.handle(..)`
|
|
|
|
|
|
|
|
|
|
Create a handler queue object.
|
|
|
|
|
```bnf
|
|
|
|
|
Queue.handle(<func>, ...<data>)
|
|
|
|
|
Queue.handle(<options>, <func>, ...<data>)
|
|
|
|
|
-> <queue>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
A handler queue is a queue that has a single handler function (`.handle(..)`)
|
|
|
|
|
that handles the queue data.
|
|
|
|
|
|
|
|
|
|
This is a shorthand for:
|
|
|
|
|
```javascript
|
|
|
|
|
var handler_queue = Queue({
|
|
|
|
|
handler: function(item){ .. },
|
|
|
|
|
..
|
|
|
|
|
},
|
|
|
|
|
.. )
|
|
|
|
|
```
|
2020-11-07 03:19:52 +03:00
|
|
|
|
2020-12-17 18:55:28 +03:00
|
|
|
<!-- XXX settings... -->
|
|
|
|
|
|
|
|
|
|
|
2020-11-07 03:19:52 +03:00
|
|
|
#### `<queue>.state`
|
|
|
|
|
|
2020-12-08 01:53:40 +03:00
|
|
|
|
2020-11-07 03:19:52 +03:00
|
|
|
#### `<queue>.start(..)`
|
|
|
|
|
|
2020-12-08 01:53:40 +03:00
|
|
|
#### `<queue>.stop(..)`
|
|
|
|
|
|
2020-11-07 03:19:52 +03:00
|
|
|
|
2020-12-08 01:53:40 +03:00
|
|
|
#### `<queue>.runTask(..)`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#### `<queue>.tasksAdded(..)` (event)
|
|
|
|
|
|
|
|
|
|
#### `<queue>.taskStarting(..)` (event)
|
|
|
|
|
|
|
|
|
|
#### `<queue>.taskFailed(..)` (event)
|
|
|
|
|
|
2020-11-28 03:47:31 +03:00
|
|
|
#### `<queue>.taskCompleted(..)` (event)
|
2020-11-07 03:19:52 +03:00
|
|
|
|
2020-11-28 03:47:31 +03:00
|
|
|
Event, triggered when a task is completed passing in its result.
|
2020-11-07 03:19:52 +03:00
|
|
|
|
|
|
|
|
|
2020-12-08 01:53:40 +03:00
|
|
|
#### `<queue>.queueEmpty(..)` (event)
|
|
|
|
|
|
|
|
|
|
|
2020-12-17 18:55:28 +03:00
|
|
|
#### `<queue>.prioritize(..)`
|
|
|
|
|
|
|
|
|
|
#### `<queue>.delay(..)`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#### `<queue>.add(..)`
|
|
|
|
|
|
|
|
|
|
#### `<queue>.clear(..)`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#### `FinalizableQueue(..)` / `FinalizableQueue.runTasks(..)` (Queue)
|
|
|
|
|
|
|
|
|
|
This is the similar as `Queue(..)` but adds two terminal states (`"done"`
|
|
|
|
|
and `"aborted"`) and a `promise`-mapping.
|
|
|
|
|
|
|
|
|
|
```bnf
|
|
|
|
|
FinalizableQueue.handle(<func>, ...<data>)
|
|
|
|
|
FinalizableQueue.handle(<options>, <func>, ...<data>)
|
|
|
|
|
-> <finalizable-queue>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
When a `<finalizable-queue>` reaches a terminal state it is frozen.
|
|
|
|
|
|
|
|
|
|
#### `<finalizable-queue>.done(..)` (event/method)
|
|
|
|
|
|
|
|
|
|
#### `<finalizable-queue>.abort(..)` (event/method)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#### `<finalizable-queue>.promise(..)`
|
|
|
|
|
|
|
|
|
|
#### `<finalizable-queue>.then(..)`
|
|
|
|
|
|
|
|
|
|
#### `<finalizable-queue>.catch(..)`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-12-08 01:53:40 +03:00
|
|
|
|
2020-11-28 03:47:31 +03:00
|
|
|
### Large task management
|
2020-11-07 03:19:52 +03:00
|
|
|
|
2020-11-28 03:47:31 +03:00
|
|
|
#### `runner.TaskManager(..)`
|
2020-11-07 03:19:52 +03:00
|
|
|
|
|
|
|
|
|
2020-11-28 03:47:31 +03:00
|
|
|
This includes [`event.EventMixin`](#eventeventmixin).
|
|
|
|
|
|
|
|
|
|
#### `<task-manager>.Task(..)`
|
|
|
|
|
|
|
|
|
|
#### `<task-manager>.sync_start`
|
|
|
|
|
|
|
|
|
|
#### `<task-manager>.record_times`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#### `<task-manager>.titled(..)`
|
|
|
|
|
|
|
|
|
|
#### `<task-manager>.send(..)`
|
|
|
|
|
|
|
|
|
|
#### `<task-manager>.stop(..)`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#### `<task-manager>.done(..)` (event)
|
|
|
|
|
|
|
|
|
|
#### `<task-manager>.error(..)` (event)
|
|
|
|
|
|
|
|
|
|
#### `<task-manager>.tasksDone(..)` (event)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#### `runner.TaskTicket(..)`
|
|
|
|
|
|
|
|
|
|
#### `runner.TaskMixin(..)`
|
2020-11-07 03:19:52 +03:00
|
|
|
|
|
|
|
|
|
2020-10-07 07:33:58 +03:00
|
|
|
|
|
|
|
|
## License
|
|
|
|
|
|
|
|
|
|
[BSD 3-Clause License](./LICENSE)
|
2020-10-07 03:53:10 +03:00
|
|
|
|
2020-10-07 07:33:58 +03:00
|
|
|
Copyright (c) 2020, Alex A. Naanou,
|
|
|
|
|
All rights reserved.
|
2020-10-07 03:53:10 +03:00
|
|
|
|
|
|
|
|
|
2020-12-17 18:55:28 +03:00
|
|
|
<!-- vim:set ts=4 sw=4 spell : -->
|