Depends
A library for ergonomic, performant, incremental computation between arbitrary types.
Why would I want that
Most applications rely on some core logic which must respond to external events. Often, the logic to transform each event in to an action is straightforward, but as the application scales, many hard to reason-with situations emerge from the combinatorial explosion of states.
Dependency graphs are an excellent code architecture to tame complexity in such scenarios.
use ;
use ;
// A `Leaf` is a node which takes new values from outside the graph.
// `Leaf` types must provide a way for code outside to update their internal state.
// This is just a simple replace for now.
// `Dependencies` are derived to state what references `Dependee` nodes need to
// calculate their state on-demand. These could be any number of other `Dependee`s
// or `Leaf`s.
// A `Dependee` i.e. its state is a pure transformation of other nodes
// This trait specifies how a `Dependee` updates its internal state given its dependencies.
// Compose a graph!
let left = default.into_leaf;
let right = default.into_leaf;
let sum = default.into_node;
let graph = MyGraph ;
// A `Visitor` is a collection which tracks which nodes have been visited each run.
let mut visitor = new;
// Resolving the graph from any node will traverse via Depth First Search, prompting
// recalculation for an node which has `State::Dirty`.
assert_eq!;
// `Forgets` which nodes have been visited.
visitor.clear;
// Recursively marks nodes as `State::Clean`.
graph.sum.clean;
// `Forgets` which nodes have been visited (whilst cleaning).
visitor.clear;
// Update the leaves. Their state is now `State::Dirty`.
graph.left.update;
graph.right.update;
// We've successfully implemented simple addition! Only nodes which have dirty parents
// will be recalculated.
assert_eq!;
Clearly, to implement a simple addition problem, a dependency graph is
overkill. However, for more complex problems, where many inputs can change
and the output is a combination of many transformations on that input (and
derivations of it), depends
can help you produce scalable, performant,
testable code out of the box.
Graphviz
Any graph built using depends
can be converted to a Graphviz representation
by passing a GraphvizVisitor
(this requires the feature graphviz
).
let graph = my_graph;
let mut visitor = new;
graph.answer.resolve;
assert_eq!;
The graph in the above example is rendered below.