streamer
Version:
Asynchronously recursive, pure function <3 via lazy streams.
55 lines (46 loc) • 1.73 kB
JavaScript
/* vim:set ts=2 sw=2 sts=2 expandtab */
/*jshint asi: true undef: true es5: true node: true devel: true
forin: false latedef: false */
/*global define: true */
!(typeof define !== "function" ? function($){ $(require, exports, module); } : define)(function(require, exports, module, undefined) {
;
var core = require('./core'),
map = core.map, merge = core.merge, list = core.list, append = core.append
function normalize(source) {
/**
Normalizes given `source` stream, so that it's guaranteed that
stop is called only once & no next is called after that.
**/
return function stream(next, stop) {
var stopped = false, reading = true
source(function onElement(element) {
if (!stopped && false !== reading)
return (reading = next(element))
}, function onStop(reason) {
return stopped ? nil : (stopped = true, stop(reason))
})
}
}
exports.normalize = normalize
function tree(isBranch, children, root) {
/**
Returns a lazy stream of the nodes in a tree, via a depth-first walk.
`isBranch` must be a function that takes one argument and returns true if
passed a node that can have children (but may not). `children` must be a
function that takes one argument and returns a stream of the children. Will
only be called on nodes for which `isBranch` returns true. `root` is the root
node of the tree.
**/
return (function walk(node) {
return function stream(next, stop) {
var $ = isBranch(node)
!(typeof($) === 'function' ? $ : list($))(function(isBranch) {
(isBranch ?
append(list(node), merge(map(walk, children(node)))) :
list(node))(next, stop)
})
}
})(root)
}
exports.tree = tree
});