FunctionSelect: Select a function that passes a condition. A functional alternative to switch-case.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

243 lines
6.5 KiB

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Source: index.js</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Source: index.js</h1>
<section>
<article>
<pre class="prettyprint source linenums"><code>'use strict';
/**
* FUSE
* FunctionSelect: Return a function based on a condition.
* @version 0.10.0
* @author Muthu Kumar (MKRhere)
*/
/**
* @callback predicate
* @param {any} value The selected Fuse value
* @returns {boolean} The Boolean result of the test
*/
/**
* @callback consequent
* @param {any} value The selected Fuse value
* @param {...any} args An arbitrary array of arguments
* @returns {any}
*/
/**
* Creates a FuseItem instance with a value and optional resolve function.
* FuseIterable constructor uses it internally, and Fuse extends FuseItem.
* Not exposed.
* @class FuseItem
*/
class FuseItem {
/**
* @param {any} value The input value
* @param {function} resolve Optional resolve function
* @constructs FuseItem
*/
constructor(value, resolve) {
this.value = value;
if (resolve) {
this.resolve = (...args) => resolve(this.value, ...args);
this.resolved = true;
}
}
/**
* Fallback resolve prototype. Returns null when called.
* Used in case a resolve is never found.
* @returns {null} null
* @memberof FuseItem
*/
resolve() {
return null;
}
}
/**
* Creates a FuseIterable instance from an array or iterable.
* @class FuseIterable
* @param {iterable} values An iterable expression as the switch
* @param {Array&lt;function>} tests Array of { test, consequent } objects
* @param {function} tests[].predicate Test function
* @param {function} tests[].consequent Consequent function
* @constructs FuseIterable
*/
class FuseIterable {
constructor(values, conditionals) {
this.values = Array.from(values).map(value =>
value instanceof FuseItem
? value
: new FuseItem(value));
this.conditionals = conditionals || [];
}
/**
* Accepts a test and consequent function each and returns a new
* FuseIterable instance.
* FuseIterable.prototype.for works a little differently than
* Fuse.prototype.for, by lazy accumulating the tests and
* resolving all the values when .resolve() is called.
* @param {callback} predicate A test callback function
* @param {callback} consequent Consequent callback function
* @returns {FuseIterable} An instance of FuseIterable
* @memberof FuseIterable
*/
on(predicate, consequent) {
return new FuseIterable(this.values, [
...this.conditionals,
{ predicate, consequent }
]);
}
/**
* Accepts a list of tuples as arguments and returns a new
* FuseIterable instance. An alternative to chaining multiple
* FuseIterable.prototype.on methods.
* @memberOf FuseIterable
* @param {...Array.&lt;function>} tuples -
* Array of [ predicate, consequent ] pairs
* @returns {FuseIterable} An instance of FuseIterable
*/
onField(...tuples) {
const conditionals = tuples.map(conditional =>
({
predicate: conditional[0],
consequent: conditional[1]
}));
return new FuseIterable(this.values, conditionals);
}
/**
* Accepts parameters during resolve time and passes them along with
* each value into the winning consequent function.
* @param {...any} args Any number of arguments
* @returns {(any|null)} Resolved value or null if it was unresolved
*/
resolve(...args) {
return this.values.map(item => {
const resolver = this.conditionals.find(conditional =>
conditional.predicate(item.value)
? conditional.consequent
: null
);
return resolver
? resolver.consequent(item.value, ...args)
: null;
});
}
}
/**
* Creates a new Fuse instance.
* @class Fuse
* @extends {FuseItem}
*/
class Fuse extends FuseItem {
/**
* Accepts a test and consequent function each and returns a new
* Fuse or FuseIterable instance.
* @param {callback} predicate A test callback function
* @param {callback} consequent Consequent callback function
* @returns {Fuse} Returns a new Fuse instance
* @memberof Fuse
*/
on(predicate, consequent) {
/* If a resolve exists, just pass on the instance
until .resolve() is called */
if (this.resolved) return this;
if (predicate(this.value)) return new Fuse(this.value, consequent);
/* If the test doesn't pass, just pass the Fuse
instance along the chain until a test passes,
or .resolve() is called */
return this;
}
/**
* Accepts a consequent function which automatically becomes resolve.
* Does not return a Fuse instance as .on after .else would be useless.
* @param {callback} consequent Consequent callback function
* @returns {Fuse} Returns new FuseItem instance
*/
else(consequent) {
return new FuseItem(this.value, consequent);
}
/**
* Accepts a value instead of a test function, and checks for strict
* equality with this.value.
* @param {any} value Any value to check against this.value
* @param {function} consequent Consequent callback function
* @returns {Fuse} An instance of Fuse
*/
is(value, consequent) {
return this.on(() => value === this.value, consequent);
}
/**
* Accepts a value instead of a test function, and checks for strict
* inequality with this.value.
* @param {any} value Any value to check against this.value
* @param {function} consequent Consequent callback function
* @returns {Fuse} An instance of Fuse
*/
not(value, consequent) {
return this.on(() => value !== this.value, consequent);
}
}
module.exports = Fuse;
module.exports.FuseIterable = FuseIterable;
</code></pre>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Fuse.html">Fuse</a></li><li><a href="FuseItem.html">FuseItem</a></li><li><a href="FuseIterable.html">FuseIterable</a></li></ul><h3><a href="global.html">Global</a></h3>
</nav>
<br class="clear">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Fri Apr 20 2018 02:24:29 GMT+0530 (IST)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>