Iterator that chains callback function execution
-
-
Class
Iterator_Cascade_Callbacks
- Method
Iterator_Cascade_Callbacks.constructor
- Static Method
*iteratorFromArray
- Static Method
*iteratorFromObject
- Static Method
iteratorFromGenerator
- Method
*iterateCallbackObjects
- Method
collect
- Method
collectToArray
- Method
collectToFunction
- Method
collectToObject
- Method
filter
- Method
limit
- Method
map
- Method
next
- Method
skip
- Method
step
- Method
take
- Method
NodeJS dependencies may be installed via NPM...
npm install
Notice as of version 0.0.1
NodeJS dependencies are for development only, ie. if utilizing this project within other applications or as a submodule, then no dependencies are required.
NodeJS projects may use npm
to install iterator-cascade-callbacks
as a dependency...
npm install iterator-cascade-callbacks
... or as a development dependency via --save-dev
command-line flag...
npm install --save-dev iterator-cascade-callbacks
... Check NodeJS Examples for details on how to import this project within your own source code.
Web projects, such has those hosted on GitHub Pages, are encouraged to utilize Git Submodules instead...
Bash Variables
_module_name='iterator-cascade-callbacks'
_module_https_url="https://github.com/javascript-utilities/iterator-cascade-callbacks.git"
_module_base_dir='assets/javascript/modules'
_module_path="${_module_base_dir}/${_module_name}"
Bash Submodule Commands
cd "<your-git-project-path>"
git checkout gh-pages
mkdir -vp "${_module_base_dir}"
git submodule add -b main\
--name "${_module_name}"\
"${_module_https_url}"\
"${_module_path}"
Suggested additions for your ReadMe.md
file so everyone has a good time with submodules
Clone with the following to avoid incomplete downloads
git clone --recurse-submodules <url-for-your-project>
Update/upgrade submodules via
git submodule update --init --merge --recursive
git add .gitmodules
git add "${_module_path}"
## Add any changed files too
git commit -F- <<'EOF'
:heavy_plus_sign: Adds `javascript-utilities/iterator-cascade-callbacks#1` submodule
**Additions**
- `.gitmodules`, tracks submodules AKA Git within Git _fanciness_
- `README.md`, updates installation and updating guidance
- `_modules_/iterator-cascade-callbacks`, Iterator that chains callback function execution
EOF
git push origin gh-pages
🎉 Excellent 🎉 your project is now ready to begin unitizing code from this repository!
Examples on how to utilize this repository
#!/usr/bin/env node
'use strict';
const {
Callback_Object,
Iterator_Cascade_Callbacks,
Stop_Iteration,
Pause_Iteration,
} = require('iterator-cascade-callbacks');
/**
* Generator that produces Fibonacci sequence
* @see {link} https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators
*/
function* fibonacci() {
let current = 0;
let next = 1;
while (true) {
let reset = yield current;
[current, next] = [next, next + current];
if (reset) {
current = 0;
next = 1;
}
}
}
const icc = new Iterator_Cascade_Callbacks(fibonacci);
icc.filter((value) => {
return value % 2 === 0;
}).skip(1).map((evens) => {
return evens / 2;
}).take(5);
const collection = icc.collect([]);
console.log(collection);
//> [ 1, 4, 17, 72, 305 ]
The above filters even numbers from fibonacci
Generator, skips the first even result, divides results by two, limits iteration to five results, and finally collects values to an array.
To achieve the same output but without Iterator_Cascade_Callbacks
class, code may be similar to...
'use strict';
let match_count = 0;
let skip_count = 0;
let collection = [];
for (let value of fibonacci()) {
if (!(value % 2 === 0)) {
continue;
}
skip_count++;
if (skip_count <= 1) {
continue;
}
collection.push(value / 2);
match_count++;
if (match_count >= 5) {
break;
}
}
console.log(collection);
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Iterator Cascade Callbacks Example</title>
<script src="/assets/javascript/modules/iterator-cascade-callbacks/iterator-cascade-callbacks.js" defer></script>
<script src="/assets/javascript/index.js" defer></script>
</head>
<body>
<code>
const counter = new Counter(<span id="code__span__counter__start">0</span>);
<br>
const icc = new Iterator_Cascade_Callbacks(counter);
<br>
<br>
const collection = icc.filter((value) => {
<div style="text-indent: 2em;">
return value % <span id="code__span__filter_modulo">2</span> === 0;
</div>
}).map((value) => {
<div style="text-indent: 2em;">
return value * <span id="code__span__map_multiplier">1</span>;
</div>
}).take(<span id="code__span__take_amount">2</span>).collect([]);
</code>
<br>
<br>
<div id="output-text__container">
<label for="output-text__results">Results: </label>
<input id="output-text__results" type="text" value="" readonly>
</div>
<br>
<div id="input-text__container">
<label for="input-text__counter__start">Counter Start: </label>
<input id="input-text__counter__start" type="text" value="0">
<br>
<label for="input-text__filter_modulo">Filter Modulo: </label>
<input id="input-text__filter_modulo" type="text" value="2">
<br>
<label for="input-text__map_multiplier">Map Multiplier: </label>
<input id="input-text__map_multiplier" type="text" value="1">
<br>
<label for="input-text__take_amount">Take Amount: </label>
<input id="input-text__take_amount" type="text" value="2">
</div>
<div id="button__container">
<input id="button__iterate" type="button" value="Iterate">
</div>
</body>
</html>
assets/javascript/index.js
'use strict';
class Counter {
constructor(value = -1) {
this.value = value;
this.done = false;
}
next() {
this.value++;
return this;
}
[Symbol.iterator]() {
return this;
}
};
window.addEventListener('load', () => {
const output_text__results = document.getElementById('output-text__results');
const input_text__counter__start = document.getElementById('input-text__counter__start');
const code__span__counter__start = document.getElementById('code__span__counter__start');
const input_text__filter_modulo = document.getElementById('input-text__filter_modulo');
const code__span__filter_modulo = document.getElementById('code__span__filter_modulo');
const input_text__map_multiplier = document.getElementById('input-text__map_multiplier');
const code__span__map_multiplier = document.getElementById('code__span__map_multiplier');
const input_text__take_amount = document.getElementById('input-text__take_amount');
const code__span__take_amount = document.getElementById('code__span__take_amount');
const button__iterate = document.getElementById('button__iterate');
button__iterate.addEventListener('click', () => {
console.error('CLICKED!');
/**
* Parse inputs
*/
let count_start = input_text__counter__start.value;
if (isNaN(count_start)) {
count_start = 0;
input_text__counter__start = count_start;
}
code__span__counter__start.innerText = count_start;
let filter_modulo = Number(input_text__filter_modulo.value);
if (isNaN(filter_modulo)) {
filter_modulo = 1;
input_text__filter_modulo.value = filter_modulo;
}
code__span__filter_modulo.innerText = filter_modulo;
let map_multiplier = Number(input_text__map_multiplier.value);
if (isNaN(map_multiplier)) {
map_multiplier = 1;
input_text__map_multiplier.value = map_multiplier;
}
code__span__map_multiplier.innerText = map_multiplier;
let take_amount = Number(input_text__take_amount.value);
if (isNaN(take_amount)) {
take_amount = 1;
input_text__take_amount.value = take_amount;
}
code__span__take_amount.innerText = take_amount;
const counter = new Counter(count_start);
const icc = new Iterator_Cascade_Callbacks(counter);
icc.filter((value) => {
return value % filter_modulo === 0;
}).map((value) => {
return value * map_multiplier;
}).take(take_amount);
const collection = icc.collect([]);
console.log('collection ->', collection);
const results = `[ ${collection.join(', ')} ]`;
output_text__results.value = results;
});
});
Documentation for classes, methods, paramaters, and custom types/data-structures
Custom error type to permanently stop iteration prematurely
const icc = new Iterator_Cascade_Callbacks([1, 2, 3, 4]);
const collection = icc.map((value, index_or_key) => {
if (index_or_key > 2) {
throw new Stop_Iteration('map says to stop at indexes greater than 2');
}
return value;
}).collect([]);
console.log(collection);
//> [ 1, 2, 3 ]
Builds new instance of Stop_Iteration
for throwing
Parameters
- {string}
message
- Error message to print
Custom error type to temporarily stop iteration prematurely
Parameters
- {string}
message
- Error message to print
Classy object for storing wrapper function state between iterations
Builds new instance of Callback_Object
to append to Iterator_Cascade_Callbacks.callbacks
list
Parameters
- {Callback_Wrapper}
callback_wrapper
- Function wrapper that handles input/output betweenCallback_Function
andIterator_Cascade_Callbacks
Calls this.wrapper
function with reference to this Callback_Object
and Iterator_Cascade_Callbacks
Parameters
- {Iterator_Cascade_Callbacks}
iterator_cascade_callbacks
- Reference toIterator_Cascade_Callbacks
instance
Iterator that chains callback function execution
Properties
-
{Dictionary}
state
- Data shared betweenCallback_Wrapper
functions on each iteration -
{Dictionary}
storage
- Data shared betweenCallback_Function
for each iteration
Instantiates new instance of Iterator_Cascade_Callbacks
from iterable
input
Parameters
- {any}
iterable
- Currently may be an array, object, generator, or iterator type
Converts Array
to GeneratorFunction
Parameters
- {any[]}
array
- List any type of values
Yields {Yielded_Tuple} [any, number]
Converts Object
to GeneratorFunction
Parameters
- {Dictionary}
dictionary
- Dictionary of key value pares
Yields {Yielded_Tuple} [any, string]
Converts Iterator class or GeneratorFunction
to Generator
Parameters
- {GeneratorFunction}
iterator
- Objects with.next()
or[Symbol.iterator]()
method defined
Yields {Yielded_Tuple} [any, number]
Converts list of this.callbacks
objects to GeneratorFunction
Yields {Callback_Object}
Collects results from this
to either an Array or Object
Parameters
-
{any[] | Object | any}
target
- Whentarget
is Array values are pushed, whentarget
is Object key value pares are assigned,callback
is required for other types -
{Collect_To_Function?|number?}
callback_or_amount
- Callback function for collecting to custom type, or amount to limit known collection object types to -
{number?}
amount
- Limit collection to no more than amount
Returns {any[] | Dictionary | undefined}
Collects results from this.next()
to an Array
Parameters
-
{any[]}
target
- Array to push collected values to -
{number?}
amount
- Limit collection to no more than amount
Returns {any[]}
Example
const icc = new Iterator_Cascade_Callbacks([5, 6, 7, 8, 9]);
const collection = icc.filter((value) => {
return value % 2 === 0;
}).collectToArray([1, 2, 3]);
console.log(collection);
//> [ 1, 2, 3, 6, 8 ]
Collects results from this.next()
to a callback function target
Parameters
-
{any}
target
- Any object or primitive, will be passed tocallback
function along withvalue
andindex_or_key
-
{Function}
callback
- Custom callback function for collecting iterated values -
{number?}
amount
- Limit collection to no more than amount
Example
const icc = new Iterator_Cascade_Callbacks({ spam: 'flavored', canned: 'ham' });
const map = new Map();
const collection = icc.collectToFunction(map, (target, value, index_or_key) => {
target.set(index_or_key, value);
});
console.log(collection);
//> Map(2) { 'spam' => 'flavored', 'canned' => 'ham' }
Collects results from this.next()
to an Object
Parameters
-
{Object}
target
- Dictionary like object to assign key value pares to -
{number?}
amount
- Limit collection to no more than amount
Returns dictionary-like object
Example
const icc = new Iterator_Cascade_Callbacks({ spam: 'flavored', canned: 'ham' });
const collection = icc.collectToObject({});
console.log(collection);
//> { spam: 'flavored', canned: 'ham' }
Sets this.value
if callback function returns truthy, else consumes this.iterator
and recomputes value for callback to test
Parameters
- {Callback_Function}
callback
- Function that determines truth ofvalue
and/orindex_or_key
for each iteration
Returns this
{Iterator_Cascade_Callbacks}
Example
const icc = new Iterator_Cascade_Callbacks([9, 8, 7, 6, 5]);
const collection = icc.filter((value) => {
return value % 2 === 0;
}).collect([]);
console.log(collection);
//> [ 8, 6 ]
Stops iteration when limit is reached
Parameters
- {number}
amount
- Max number of values to compute
Returns this
{Iterator_Cascade_Callbacks}
Example
const icc = new Iterator_Cascade_Callbacks([1, 2, 3, 4]);
const collection = icc.limit(2).collect([]);
console.log(collection);
//> [1, 2]
Notes
-
Useful when iterating over data of indeterminate, or infinite, length
-
More predictable if ordered at the end of
this.callbacks
list -
Callbacks exist when
amount
is reached will be called prior to throwingStop_Iteration
Applies callback
to modify value
and/or index_or_key
for each iteration
Parameters
- {Callback_Function}
callback
- Function may modifyvalue
and/orindex_or_key
Returns this
{Iterator_Cascade_Callbacks}
Example
const icc = new Iterator_Cascade_Callbacks([9, 8, 7, 6, 5]);
const collection = icc.filter((value) => {
return value % 2 === 0;
}).map((value) => {
return value / 2;
}).collect([]);
console.log(collection);
//> [4, 3]
Notes
- If callback does not return
Yielded_Tuple
(array), then results from callback are used asvalue
and initialindex_or_key
is reused
Updates this.value
from chaining this.callbacks
list, and this.done
from this.iterator.next()
Returns this
{Iterator_Cascade_Callbacks}
Example
const icc = new Iterator_Cascade_Callbacks([1, 2, 3, 4]);
for (let [value, index_or_key] of icc) {
console.log('index_or_key ->', index_or_key, 'value ->', value);
}
//> index_or_key -> 0 value -> 1
//> index_or_key -> 1 value -> 2
//> index_or_key -> 2 value -> 3
//> index_or_key -> 3 value -> 4
Skip number of iterations
Parameters
- {number} amount - Number of iterations to skip past
Returns this
{Iterator_Cascade_Callbacks}
Example
const icc = new Iterator_Cascade_Callbacks([0, 1, 2, 3, 4, 5]);
const collection = icc.skip(2).collect([]);
console.log(collection);
//> [ 2, 3, 4, 5 ]
Step over every n iterations
Parameters
- {number}
amount
- Number of iterations to step over
Returns this
{Iterator_Cascade_Callbacks}
Example
const icc = new Iterator_Cascade_Callbacks([0, 1, 2, 3, 4, 5]);
const collection = icc.step(1).collect([]);
console.log(collection);
//> [ 1, 3, 5 ]
Pauses/breaks iteration when limit is reached
Parameters
- {number}
amount
- Number of values to compute before pausing
Returns this
{Iterator_Cascade_Callbacks}
Throws {Pause_Iteration}
Example
const icc = new Iterator_Cascade_Callbacks([1, 2, 3, 4]);
icc.take(2);
const collection_one = icc.collect([]);
console.log(collection_one);
//> [ 1, 2 ]
const collection_two = icc.collect([]);
console.log(collection_two);
//> [ 3, 4 ]
Notes
- If immediately collecting to an object, consider using
collect()
method instead
Descriptions of data structures and generic behaviour
Classy object for storing wrapper function state between iterations
Properties
-
{Callback_Wrapper}
wrapper
- Wrapper for callback function that parses inputs and outputs -
{Dictionary}
storage
- Generic dictionary like object
Documentation for custom type definitions
Generic callback function for parsing and/or mutating iterator data
Parameters
-
{any}
value
- First half ofYielded_Tuple
stored inthis.value
orvalue
fromthis.iterator.next()
-
{Index_Or_Key}
index_or_key
- Either astring
ornumber
depending upon iterable type -
{Callback_Function_References}
references
- Dictionary with reference tothis
Iterator_Cascade_Callbacks
andthis
Callback_Object
Object with references to Iterator_Cascade_Callbacks
and Callback_Object
instances
Properties
-
{Iterator_Cascade_Callbacks}
iterator_cascade_callbacks
- Instance reference tothis
ofIterator_Cascade_Callbacks
-
{Callback_Object}
callback_object
- Instance reference tothis
ofCallback_Object
Wrapper for callback function that parses inputs and outputs
Parameters
-
{Callback_Object}
callback_object
- Instance reference tothis
ofCallback_Object
-
{Iterator_Cascade_Callbacks}
iterator_cascade_callbacks
- Instance reference tothis
ofIterator_Cascade_Callbacks
Generic dictionary like object
Example
const data: Dictionary = { key: 'value' };
Array index
or Object key
or Generator count
Example
const key: Index_Or_Key = 'key';
const index: Index_Or_Key = 42;
Array with value
and index_or_key
entries
Example
const result: Yielded_Tuple = ['spam', 3];
This repository may not be feature complete and/or fully functional, Pull Requests that add features or fix bugs are certainly welcomed.
Options for contributing to iterator-cascade-callbacks and javascript-utilities
Start making a Fork of this repository to an account that you have write permissions for.
- Add remote for fork URL. The URL syntax is
[email protected]:<NAME>/<REPO>.git
...
cd ~/git/hub/javascript-utilities/iterator-cascade-callbacks
git remote add fork [email protected]:<NAME>/iterator-cascade-callbacks.git
- Commit your changes and push to your fork, eg. to fix an issue...
cd ~/git/hub/javascript-utilities/iterator-cascade-callbacks
git commit -F- <<'EOF'
:bug: Fixes #42 Issue
**Edits**
- `<SCRIPT-NAME>` script, fixes some bug reported in issue
EOF
git push fork main
Note, the
-u
option may be used to setfork
as the default remote, eg.git push -u fork main
however, this will also default thefork
remote for pulling from too! Meaning that pulling updates fromorigin
must be done explicitly, eg.git pull origin main
- Then on GitHub submit a Pull Request through the Web-UI, the URL syntax is
https://github.com/<NAME>/<REPO>/pull/new/<BRANCH>
Note; to decrease the chances of your Pull Request needing modifications before being accepted, please check the dot-github repository for detailed contributing guidelines.
Thanks for even considering it!
Via Liberapay you may on a repeating basis.
Regardless of if you're able to financially support projects such as iterator-cascade-callbacks that javascript-utilities maintains, please consider sharing projects that are useful with others, because one of the goals of maintaining Open Source repositories is to provide value to the community.
-
GitHub --
Microsoft/TypeScript
-- Issue3841
-- T.constructor should be of type T -
StackOverflow -- Interfaces with construct signatures not type checking
Iterator that chains callback function execution
Copyright (C) 2021 S0AndS0
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, version 3 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
For further details review full length version of AGPL-3.0 License.