1 | const { Set } = require("@algebraic/collections");
|
2 |
|
3 |
|
4 |
|
5 | module.exports = function reduce(children, cyclic = false)
|
6 | {
|
7 | return function reduce(f, accum, node)
|
8 | {
|
9 | return cyclic ?
|
10 | reduce_(
|
11 | children,
|
12 | ([visited, accum], node) =>
|
13 | (console.log(node + " " + visited.has(node) + " " + visited.size + " " + visited), visited.has(node) ?
|
14 | [visited, accum] :
|
15 | [visited.add(node), f(accum, node)]),
|
16 | [Set(Object)(), accum],
|
17 | node)[1] :
|
18 | reduce_(children, f, accum, node)
|
19 | }
|
20 | }
|
21 |
|
22 | module.exports.cyclic = function reduceCyclic(children, f, accum, node)
|
23 | {
|
24 | var result;
|
25 |
|
26 | Set(Object)([node]).withMutations(set =>
|
27 | result = reduceCyclic_(children, set, f, accum, node)[1]);
|
28 |
|
29 | return result;
|
30 | }
|
31 |
|
32 |
|
33 | function reduceCyclic_(children, visited, f, accum, node)
|
34 | {
|
35 | const unvisited = Set(Object)(children(node)).subtract(visited);
|
36 | const outVisited = visited.union(unvisited);
|
37 |
|
38 | return unvisited.reduce(
|
39 | ([visited, accum], node) =>
|
40 | reduceCyclic_(children, visited, f, accum, node),
|
41 | [visited, f(accum, node)]);
|
42 | }
|
43 |
|
44 | function reduce_(children, f, accum, node)
|
45 | {console.log("WILL ITERATE OVER " + children(node));
|
46 | return children(node).reduce(
|
47 | (accum, node) => reduce_(children, f, accum, node),
|
48 | f(accum, node));
|
49 | }
|