Add a covariant `copy` method on `Graph` (#109)
Summary: Clients of `Graph` that wish to treat the graph as immutable will benefit from a `copy` method. We should provide it on `Graph` instead of asking clients to reimplement it because it affords us the opportunity to get the type signature right: in particular, copying should allow upcasting of the type parameters, even though `Graph` itself is invariant. Paired with @dandelionmane. Test Plan: Unit tests added. Run `yarn flow` and `yarn test`. To check that downcasting is not allowed, change the types in the new static test case in `graph.test.js` to be contravariant instead of covariant, and note that `yarn flow` fails. wchargin-branch: graph-copy
This commit is contained in:
parent
007cf88172
commit
26508051a4
|
@ -41,6 +41,10 @@ export class Graph<NP, EP> {
|
||||||
this._inEdges = new AddressMap();
|
this._inEdges = new AddressMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
copy(): Graph<$Supertype<NP>, $Supertype<EP>> {
|
||||||
|
return Graph.mergeConservative(new Graph(), this);
|
||||||
|
}
|
||||||
|
|
||||||
equals(that: Graph<NP, EP>): boolean {
|
equals(that: Graph<NP, EP>): boolean {
|
||||||
return this._nodes.equals(that._nodes) && this._edges.equals(that._edges);
|
return this._nodes.equals(that._nodes) && this._edges.equals(that._edges);
|
||||||
}
|
}
|
||||||
|
|
|
@ -631,5 +631,32 @@ describe("graph", () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("copy", () => {
|
||||||
|
it("separates references from the original", () => {
|
||||||
|
const g1 = demoData.advancedMealGraph();
|
||||||
|
const g2 = g1.copy();
|
||||||
|
const newNode = () => ({
|
||||||
|
address: demoData.makeAddress("brand-new"),
|
||||||
|
payload: 777,
|
||||||
|
});
|
||||||
|
g2.addNode(newNode());
|
||||||
|
expect(g1.getNode(newNode().address)).toBeUndefined();
|
||||||
|
expect(g2.getNode(newNode().address)).toEqual(newNode());
|
||||||
|
});
|
||||||
|
|
||||||
|
it("yields a result equal to the original", () => {
|
||||||
|
const g1 = demoData.advancedMealGraph();
|
||||||
|
const g2 = g1.copy();
|
||||||
|
expect(g1.equals(g2)).toBe(true);
|
||||||
|
expect(g1.equals(demoData.advancedMealGraph())).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
function itAllowsUpcastingPayloadTypes(
|
||||||
|
g: Graph<{x: string, y: number}, boolean>
|
||||||
|
): Graph<{x: string}, ?boolean> {
|
||||||
|
return g.copy();
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue