tiny-cps
Tiny but powerful goodies for Continuation-Passing-Style (CPS) functions
Migration notice
The most advanced version of this package is migrating to https://www.npmjs.com/package/cpsfy
Please use cpsfy
instead of tiny-cps
// older package, will remain unchangednpm install tiny-cps
No dependency policy. For maximum security, this package is intended not to have dependencies ever.
CPS function
Any function
//cb1, cb2, ... are called any number of times with any // (possibly varying each time) number of argumentsconst cpsFn = { ... }
that expects to be called with several (possibly zero) functions (callbacks) as arguments. The number of callbacks may vary each time cpsFn
is called. Once called and running, cpsFn
may call any of the callbacks cbn
any (possibly zero) number of times with any number m
of arguments (x1, ..., xm)
, where m
may also vary from call to call. The m
-tuple (vector) (x1, ..., xm)
is regarded as the output of cpsFn
passed to the n
the callback:
// (x1, ..., xm) is output from nth callback whenever // is called
In other words, a CPS function receives any number of callbacks that it may call in any order any number of times at any moments immediately or in the future with any number of arguments.
API in brief
const map chain filter scan CPS pipeline =
Each of the map
, chain
, filter
, scan
operators can be used in 3 ways:
// 'map' as curried functioncpsFn// 'map' method provided by the 'CPS' wrapper// 'cpsFn' is piped into 'map(f)' via 'pipeline' operator
The wrapped CPS function CPS(cpsFn)
has all operators available as methods, while it remains plain CPS function, i.e. can be called with the same callbacks:
f1 f2 ... // is equivalent to
chaining
// as methods // of as functional pipeline
map(...functions)(cpsFunction)
cpsFn
For each n
, apply fn
to each output from the n
th callback of cpsFn
.
map
Result of applying New CPS function that calls its n
th callback cbn
as
whenever cpsFn
calls its n
th callback.
map
Example of const fs = const readFile = fs // CPS function // read file and convert all letters to uppercaseconst getCaps = // orconst getCaps = // orconst getCaps = // getCaps is CPS function, call with any callback // => file content is capitalized and printed
chain(...functions)(cpsFunction)
cpsFn
where each fn
is a curried function
// fn(x1, x2, ...) is expected to return a CPS functionconst fn = { ... }
The chain
operator applies each fn
to each output from the n
th callback of cpsFn
, however, the CPS ouptup of fn
is passed ahead instead of the return value.
chain
Result of applying New CPS function newCpsFn
that calls fn(x1, x2, ...)
whenever cpsFn
passes output (x1, x2, ...)
into its n
th callback, and collects all outputs from all callbacks of all fn
s. Then for each fixed m
, outputs from the m
th callbacks of all fn
s are collected and passed into the m
th callback cbm
of newCpsFn
:
// is called whenever // is called where// cbmFn is the mth callback of fn
chain
Example of const writeFile = // CPS function fs const copy = // CPS function// orconst copy = // orconst copy = // copy is a CPS function, call it with any callback // => file content is capitalized and printed
filter(...predicates)(cpsFunction)
cpsFn
where each predn
is the n
th predicate function used to filter output from the n
th callback of cpsFn
.
chain
Result of applying New CPS function that calls its n
th callback cbn(x1, x2, ...)
whenever (x1, x2, ...)
is an output from the n
th callback of cpsFun
and
== true
filter
Example of // only copy text if it is not emptyconst copyNotEmpty = // copyNotEmpty is CPS function, call with any callback
scan(...reducers)(...initialValues)(cpsFunction)
Similar to reduce
, except that all partial accumulated values are passed into callback whenever there is new output.
x1 x2 ...cpsFncpsFnx1 x2 ...x1 x2 ...
where each redn
is a reducer
// compute new accumulator value from the old one
// and the tuple of current values (y1, y2, ...)
const redn = (acc, y1, y2, ...) => ...
scan
Result of applying New CPS function whose output from the n
the callback is the n
th accumulated value accn
. Upon each output (y1, y2, ...)
, the new acculated value redn(accn, y1, y2, ...)
is computed and passed into the callback. The nth value xn
serves in place of acc
at the start, similar to reduce
. Note that the initial values (x1, x2, ...)
must be passed as curried arguments to avoid getting mixed with reducers.
scan
Example of // CPS function with 2 callbacks, a click on one// of the buttons sends '1' into respective callbackconst getVotes = { upvoteButton downvoteButton }const add = acc + x// count numbers of up- and downvotes and // pass into respective callbacksconst countVotes = 0 0getVotes // orconst countVotes = 0 0 // countVotes is CPS function that we can call // with any pair of callbacks
More details?
This README.md
is kept minimal to reduce the package size. For more human introduction, motivation, use cases and other details, please see DOCUMENTATION.