# [−][src]Crate calc_graph

Use this crate to split a calculation into related sub-calculations, known as nodes.

You can push information from outside into one or more source nodes, and you can read results from one or more output nodes. Values are only calculated as they're needed, and cached as long as their inputs don't change. This means that recalculations are efficient when you only change some of the inputs, and if you don't request the value from an output node, its value is never calculated.

# Example

let graph = Graph::new(); // create a Graph object let mut source = graph.source(42); // define one or more nodes for your inputs let mut output = source.clone().map(|x| x + 1); // build one or more nodes for your outputs assert_eq!(43, output.get_mut()); // read values from your output nodes source.set(99); // push new values to the input nodes... assert_eq!(100, output.get_mut()); // ...and read the output nodes

# Sharing

Func nodes (created by `Node::map`

, `Node::zip`

and related methods) own their inputs (precedent nodes). When you
have a node that acts as an input to two or more func nodes, you need to use `shared()`

first. You can then use this shared node multiple times via `clone()`

:

let input_node = calc_graph::const_(42).shared(); let mut output1_node = input_node.clone().map(|x| x + 1); let mut output2_node = input_node.map(|x| x * x); assert_eq!(43, output1_node.get_mut()); assert_eq!(1764, output2_node.get_mut());

You can have multiple `Graph`

objects in the same program, but when you define a new node, its precedents must
come from the same graph.

# Boxing

A `Node`

object remembers the full type information of its precedent nodes as well as the closure used to calculate
its value. This means that the name of the `Node`

type can be very long, or even impossible to write in the source
code. In this situation you can use:

let func_node: Node<Func1<_, i32, _>> = input_node.map(|x| x + 1); let output_node: BoxNode<i32> = func_node.boxed();

A call to `boxed()`

is also needed if you want a variable that can hold either one or another node; these nodes can
have different concrete types, and calling `boxed()`

on each of them gives you a pair of nodes that have the same
type.

# Threading

`Node<Source>`

, `SharedNode`

and `BoxedNode`

objects are `Send`

and `Sync`

, meaning they can be passed between
threads. Calculations are performed on the thread that calls `node.get()`

. Calculations are not parallelised
automatically, although you can read separate output nodes from separate threads, even if they share parts of the
same graph as inputs.

let graph = Graph::new(); let input_node = graph.source(41); let output_node = input_node.clone().map(|x| x * x).shared(); assert_eq!(1681, output_node.get()); let t = thread::spawn({ let input_node = input_node.clone(); let output_node = output_node.clone(); move || { input_node.update(|n| { *n += 1; true }); output_node.get() } }); assert_eq!(1764, t.join().unwrap()); input_node.update(|n| { *n += 1; true }); assert_eq!(1849, output_node.get());

`zip`

, `zip_update`

and others

Use `zip()`

, `map2()`

and related functions to create a new node that calculates its value from a `FnMut`

provided
by you and the values from one or more other nodes. For large objects, recalculating these nodes can be
inefficient, as your `FnMut`

returns a fresh object every time, which is cloned wherever it is needed.

For more efficiency you can use `zip_update()`

, `map2_update()`

and related functions. These work the same as their
non-`update`

equivalents, except that:

- You provide the initial value of the new node when you create it
- Your
`FnMut`

takes a`&mut T`

as its first parameter. You update this value in place. - Your
`FnMut`

returns`true`

if it changed value in the`&mut T`

, or`false`

otherwise. In turn, this determines whether dependent nodes are recalculated.

A useful technique for large objects is to put an `Arc<T>`

in the node. When you recalculate the node, use
`Arc::make_mut`

to update the object in place where possible and avoid allocating a new `Arc`

.

let input_node = graph.source(42); let mut output_node = input_node.clone().map_update(Arc::new([0; 1024]), |big_array, x| { let new_value = x * x; let big_array_ref = Arc::make_mut(big_array); if big_array_ref[0] == new_value { false } else { big_array_ref[0] = new_value; true } }); assert_eq!(1764, output_node.get_mut()[0]); input_node.update(|n| { *n += 1; true }); assert_eq!(1849, output_node.get_mut()[0]);

## Structs

Const | Calculates a node's value by returning the same value every time. |

Func1 | Calculates a value from another node. |

Func2 | Calculates a value from 2 nodes. |

Func3 | Calculates a value from 3 nodes. |

Func4 | Calculates a value from 4 nodes. |

Func5 | Calculates a value from 5 nodes. |

Func6 | Calculates a value from 6 nodes. |

Func7 | Calculates a value from 7 nodes. |

Func8 | Calculates a value from 8 nodes. |

Graph | Returns new |

Inspect | Provides the opportunity to inspect a node's value without changing it. |

Lazy | Calculates a node's value by calling a function on demand and caching the result. |

Node | Represents a value within the graph. |

Source | Holds a value that can be updated directly from outside the graph. |

Update1 | Calculates a value from the value currently in this node and another node. |

Update2 | Calculates a value from the value currently in this node and 2 nodes. |

Update3 | Calculates a value from the value currently in this node and 3 nodes. |

Update4 | Calculates a value from the value currently in this node and 4 nodes. |

Update5 | Calculates a value from the value currently in this node and 5 nodes. |

Update6 | Calculates a value from the value currently in this node and 6 nodes. |

Update7 | Calculates a value from the value currently in this node and 7 nodes. |

Update8 | Calculates a value from the value currently in this node and 8 nodes. |

## Traits

Calc | Calculates a node's value. |

## Functions

const_ | Returns a node whose value never changes. |

lazy | Returns a node whose value is calculated once on demand and cached. |

## Type Definitions

BoxNode | A node returned by |

SharedNode | A node returned by |