-
-
Notifications
You must be signed in to change notification settings - Fork 11
defs
defs
is a module, which defines all special constants and convenience methods
used in chain().
Its properties are mixed in or otherwise duplicated and re-exported in other modules
like chain()
.
The example of usage:
import {none} from 'stream-chain/defs.js';
// const {none} = require('stream-chain/defs.js');
none
is a special value, which terminates the chain and produces no value.
// import chain, {none} from 'stream-chain';
// import {chain, none} from 'stream-chain';
// const {chain, none} = require('stream-chain');
import chain from 'stream-chain';
import {none} from 'stream-chain/defs.js';
// a filter
dataSource
.pipe(chain([
x => x * x,
x => x % 2 == 0 ? none : x,
x => 2 * x + 1
]));
// skips even values
// if dataSource produces: 1, 2, 3
// then the result will be: 3, 19
This is the definition of none
:
const none = Symbol.for('object-stream.none');
stop
is a special value, which terminates the chain, produces no value, and stops further processing. Usually, it is used to terminate potentially infinite generators.
// import chain, {stop} from 'stream-chain';
// const {chain, stop} = require('stream-chain');
import chain from 'stream-chain';
import {stop} from 'stream-chain/defs.js';
chain([
function* () { for (let i = 0; ; ++i) yield i; }
n => n > 1000 ? stop : n,
]);
// a stream produces numbers from 0 to 1000 inclusively
This is the definition of stop
:
const stop = Symbol.for('object-stream.stop');
Important: stop
works only within function chain segments created by gen() or
fun(). The native streams do not support this feature treating it as none
.
Helper functions to mark values as final. A final value stops the chain and returns its value.
Important: this feature works only within function chain segments created by gen() or fun(). The native streams do not support this feature treating its payload as a regular value.
Used internally to mark a value as a final value. The definition:
const finalSymbol = Symbol.for('object-stream.final');
This is a helper factory function, which can be used in by chained functions. It returns a special value, which terminates the chain and uses the passed value as the result of the chain.
// import chain, {finalValue} from 'stream-chain';
// const {chain, finalValue} = require('stream-chain');
import chain from 'stream-chain';
import {finalValue} from 'stream-chain/defs.js';
dataSource
.pipe(chain([[
x => x * x,
x => finalValue(x),
x => 2 * x + 1 // will be skipped
]]));
// if dataSource produces: 1, 2, 3
// then the result will be: 1, 4, 9
isFinalValue(value)
is a companion to finalValue()
. It checks if a value was marked as final returning a standard truthy/falsy result.
// import chain, {finalValue, isFinalValue} from 'stream-chain';
// const {chain, finalValue, isFinalValue} = require('stream-chain');
import chain from 'stream-chain';
import {finalValue, isFinalValue} from 'stream-chain/defs.js';
dataSource
.pipe(chain([
x => {
let result = finalValue(x);
// ...
if (isFinalValue(result)) {
// do something
} else {
// do something else
}
// ...
},
// the rest of pipeline
]));
getFinalValue(value)
is a companion to finalValue()
and isFinalValue()
. Its argument should be a wrapped final value. Its return will be an unwrapped value.
// import chain, {finalValue, isFinalValue, getFinalValue} from 'stream-chain';
// const {chain, finalValue, isFinalValue, getFinalValue} = require('stream-chain');
import chain from 'stream-chain';
import {finalValue, isFinalValue, getFinalValue} from 'stream-chain/defs.js';
dataSource
.pipe(chain([
x => {
let result = finalValue(42);
// ...
if (isFinalValue(result)) {
const value = getFinalValue(result);
console.log(value);
// do something
} else {
console.log(result);
// do something else
}
// ...
},
// the rest of pipeline
]));
The right way to return multiple values is to use a generator function. Sometimes it is not possible to do that for some reason, e.g., because of performance considerations or for simplicity.
That's why there are helper functions that allow you to return multiple values from regular functions.
The obvious downside is that a generator function sends each value down the chain as soon as it is produced, while a regular function will accumulate the values in an array before they are sent down the chain as multiple values.
The other reason for this facility is historical: the stream-chain
library was originally designed
when generators were not available. Now it can be used for backward compatibility.
Used internally to mark a value as multiple values. The definition:
const manySymbol = Symbol.for('object-stream.many');
This is a helper factory function, which is used to wrap arrays to be interpreted as multiple values returned from a function.
// import chain, {many} from 'stream-chain';
// const {chain, many} = require('stream-chain');
import chain from 'stream-chain';
import {many} from 'stream-chain/defs.js';
dataSource
.pipe(chain([x => many([x, x + 1, x + 2])]));
// if dataSource produces: 1, 5
// then the result will be: 1, 2, 3, 5, 6, 7
isMany(value)
is a companion to many()
. It checks if a value was marked as multiple values returning a standard truthy/falsy result.
// import chain, {many, isMany} from 'stream-chain';
// const {chain, many, isMany} = require('stream-chain');
import chain from 'stream-chain';
import {many, isMany} from 'stream-chain/defs.js';
dataSource
.pipe(chain([
x => {
let result = many([x, x + 1]);
// ...
if (isMany(result)) {
// do something
} else {
// do something else
}
// ...
},
// the rest of pipeline
]));
getManyValues(value)
is a companion to many()
and isMany()
. Its argument should be a wrapped multiple value. Its return will be an unwrapped value (an array of values).
// import chain, {many, isMany, getManyValues} from 'stream-chain';
// const {chain, many, isMany, getManyValues} = require('stream-chain');
import chain from 'stream-chain';
import {many, isMany, getManyValues} from 'stream-chain/defs.js';
dataSource
.pipe(chain([
x => {
let result = many([1, 42, 99]);
// ...
if (isMany(result)) {
const values = getManyValues(result);
console.log(values);
// do something
} else {
console.log(result);
// do something else
}
// ...
},
// the rest of pipeline
]));
Helper functions to mark a function as being flushable. A flushable function will be called
when the end of the stream is reached. When it happens, it will be called with a special value
none
(see above). This value is never used in the normal course of processing. When it happens,
the function should produce delayed values, if any.
Unmarked functions are not flushable and will not be called when the end of the stream is reached.
Used internally to mark a function as being flushable. The definition:
const flushSymbol = Symbol.for('object-stream.flush');
This function marks a function as being flushable. Its arguments are:
-
fn
is the function to be marked as flushable. -
final
is an optional function that will be called when the end of the stream is reached with no arguments. Otherwise,fn
will be called with a single argumentnone
(see above). Defaults tonull
.
It returns the augmented/modified function.
// import chain, {none, flushable} from 'stream-chain';
// const {chain, none, flushable} = require('stream-chain');
import chain from 'stream-chain';
import {none, flushable} from 'stream-chain/defs.js';
let acc = 0;
dataSource
.pipe(chain([
flushable(x => {
if (x === none) {
return acc; // return the accumulated value
}
acc += x;
return none; // produce no result
})
]));
// if dataSource produces: 1, 2, 3
// then the result will be: 6
The same example can be reformulated like that:
let acc = 0;
dataSource
.pipe(chain([
flushable(
x => void acc += x,
() => acc
)
]));
// if dataSource produces: 1, 2, 3
// then the result will be: 6
isFlushable(fn)
is a companion to flushable()
. It checks if a function is marked as flushable.
It is mostly used internally.
Helper functions to mark a function as being a wrapper for a list of functions. A function list is an array of functions used in chains. It is a feature used internally to optimize pipelines: when available a function list is inlined into the pipeline instead of using the wrapper function. It is used by gen and fun modules.
This optimization is used for performance reasons and is enabled by default.
In some cases this it can cause logical problems. For example, if you use finalValue() it will not work as expected if you use a function list. Essentially it will be globalized. If your intention was to confine the final value to a specific segment, use clearFunctionList() to suppress the optimization.
Used internally to mark a function as being derived from a function list. The definition:
const fListSymbol = Symbol.for('object-stream.fList');
This function marks a value as being derived from a function list. Its arguments are:
-
value
is the value to be marked, usually a function. -
fns
is an array of functions.
It returns the augmented/modified value.
This function checks if a value is derived from a function list. It is mostly used internally.
This function extracts the function list from a value. It is mostly used internally.
In some cases we want to suppress the function list optimization and use the wrapper function as is. A good example would be final values scoped for a specific function list. This function clears the function list from a value suppressing the optimization.
It returns fn
.
Example:
import {gen, clearFunctionList} from 'stream-chain';
// treated as a wrapper, the functions will be inlined
const p1 = gen(x => x + 1, x => x * x);
// treated as an opaque function
const p2 = clearFunctionList(gen(x => x + 1, x => x * x));
const c1 = gen(p1, p2);
// effectively the same as:
const c2 = gen(x => x + 1, x => x * x, p2);
Used to terminate the processing of a value by a pipeline. It can be thrown by any function in the pipeline.
Usually returning the stop
value is more convenient than throwing it.
// import chain, {Stop} from 'stream-chain';
// const {chain, Stop} = require('stream-chain');
import chain from 'stream-chain';
import {Stop} from 'stream-chain/defs.js';
chain([
function* () { for (let i = 0; ; ++i) yield i; }
n => {
if (n > 1000) throw new Stop();
return n;
}
]);
// a stream produces numbers from 0 to 1000 inclusively