Skip to content

Commit

Permalink
minor(vestjs-runtime): IsolateWalker.reduce
Browse files Browse the repository at this point in the history
  • Loading branch information
ealush committed Jun 7, 2024
1 parent e626c4d commit e6380eb
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 1 deletion.
19 changes: 19 additions & 0 deletions packages/vestjs-runtime/src/IsolateWalker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,25 @@ export function walk(
}
}

export function reduce<T>(
startNode: TIsolate,
callback: (acc: T, isolate: TIsolate, breakout: CB<void>) => T,
initialValue: T,
visitOnly?: VisitOnlyPredicate,
): T {
let acc = initialValue;

walk(
startNode,
(node, breakout) => {
acc = callback(acc, node, breakout);
},
visitOnly,
);

return acc;
}

// This function returns true if the given predicate function returns true for any Isolate object in the tree.
// If visitOnly is provided, only Isolate objects that satisfy the predicate are visited.
export function some(
Expand Down
78 changes: 77 additions & 1 deletion packages/vestjs-runtime/src/__tests__/IsolateWalker.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { TIsolate } from 'Isolate';
import { walk } from 'IsolateWalker';
import { walk, reduce } from 'IsolateWalker';

type WalkedNode = TIsolate<{ id: string }>;

Expand Down Expand Up @@ -95,3 +95,79 @@ describe('walk', () => {
});
});
});

describe('reduce', () => {
let node = {} as unknown as TIsolate<{ value: number }>;
beforeEach(() => {
node = {
data: { value: 1 },
children: [
{
data: { value: 2 },
children: [
{ data: { value: 1 }, $type: 's' },
{
data: { value: 2 },
children: [{ data: { value: 0 } }, { data: { value: 1 } }],
},
{ data: { value: 1 }, $type: 's' },
],
},
{ data: { value: 0 } },
],
} as unknown as TIsolate<{ value: number }>;
});

it('Should return the accumulated value of the tree', () => {
const sum = reduce(node, (acc, isolate) => acc + isolate.data.value, 0);
expect(sum).toBe(8);
});

it('Should traverse the tree in a depth-first order', () => {
const visited: string[] = [];
reduce(
node,
(acc, isolate) => {
visited.push(isolate.data.value);
return acc;
},
'',
);

expect(visited).toEqual([1, 0, 1, 2, 1, 2, 0, 1]);
});

describe('Breakout', () => {
it('Should stop the walk when breakout is called', () => {
const visited: Array<number> = [];
reduce(
node,
(acc, isolate, breakout) => {
visited.push(isolate.data.value);
if (isolate.data.value === 2) {
breakout();
}
return acc;
},
'',
);

expect(visited).toEqual([1, 0, 1, 2]);
});
});

describe('VisitOnly', () => {
it('Should only visit nodes that satisfy the predicate', () => {
const output = reduce(
node,
(acc, isolate) => {
return acc + isolate.data.value;
},
0,
isolate => isolate.$type === 's',
);

expect(output).toBe(2);
});
});
});

0 comments on commit e6380eb

Please sign in to comment.