-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmutable_chain.js
More file actions
69 lines (62 loc) · 2.19 KB
/
mutable_chain.js
File metadata and controls
69 lines (62 loc) · 2.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/**
* List-Wrapper Based Reference Management Pattern (JavaScript Implementation)
*
* Uses array wrappers as indirection layer for safe mutation during iteration.
*
* PATTERN: aLink.to = [aData] instead of aLink.to = aData
*
* BENEFITS:
* - Shared reference indirection (update contents, all refs see it)
* - Mutable identity (array object stays same, contents change)
* - Safe deletion during iteration (no "deleted" flag needed)
*
* DELETION: A->B->C becomes A->C by updating A.to[0] = C, C.from[0] = A
*/
/** Create bidirectional link using array wrappers */
function linkToAndFrom(aLink, aData) {
aLink.to = [aData];
aData.from = [aLink];
}
/** Remove node by updating array CONTENTS (not references) */
function linkDataRemove(aLink) {
const predecessor = aLink.from[0];
const successor = aLink.to[0];
predecessor.to[0] = successor; // A->B->C becomes A->C
successor.from[0] = predecessor; // C's predecessor: B -> A
}
/** Generator iterator - handles deletion gracefully */
function* linkIterator(aLink, reverse = false) {
const directionKey = reverse ? "from" : "to";
const terminalCheck = reverse ? "initial" : "terminal";
while (true) {
const nextNode = aLink[directionKey][0];
if (nextNode[terminalCheck]) break;
yield nextNode;
aLink = nextNode;
}
}
// ============================================================================
// EXAMPLE USAGE
// ============================================================================
const link1 = { initial: true };
const data1 = { data: "data1!" };
const data2 = { data: "data2!" };
const data3 = { data: "data3!" };
const terminal = { terminal: true };
linkToAndFrom(link1, data1);
linkToAndFrom(data1, data2);
linkToAndFrom(data2, data3);
linkToAndFrom(data3, terminal);
console.log("Forward iteration (delete data1):");
for (const iData of linkIterator(link1)) {
if (iData.data === "data1!") {
console.log(" removing:", iData.data);
linkDataRemove(iData);
} else {
console.log(" -", iData.data);
}
}
console.log("\nReverse iteration (terminal -> link1):");
for (const iData of linkIterator(terminal, true)) {
console.log(" -", iData.data);
}